Загрузка данных


Отлично, Quest 9 готов.

По скринам видно:

make strcat

собрал:

../../build/Quest_9

Тесты strcat прошли:

strcat Result: SUCCESS

Память тоже чистая:

All heap blocks were freed -- no leaks are possible
ERROR SUMMARY: 0 errors

Значит сейчас у нас:

Quest 6 — s21_strlen — OK
Quest 7 — s21_strcmp — OK
Quest 8 — s21_strcpy — OK
Quest 9 — s21_strcat — OK

Переходим к Quest 10 — s21_strchr.

⸻

Quest 10 — s21_strchr

Функция s21_strchr должна искать первое вхождение символа в строке.

Например:

строка: "hello"
ищем: 'e'
результат: указатель на "ello"

Если символ не найден — вернуть NULL.

Если ищем '\0' — вернуть указатель на конец строки.

⸻

Шаг 1. Открой s21_string.h

Ты сейчас в папке:

src/s21_string

Введи:

nano s21_string.h

Полностью замени содержимое на это:

#ifndef S21_STRING_H
#define S21_STRING_H
#include <stddef.h>
size_t s21_strlen(const char *str);
int s21_strcmp(const char *str1, const char *str2);
char *s21_strcpy(char *destination, const char *source);
char *s21_strcat(char *destination, const char *source);
char *s21_strchr(const char *str, int symbol);
#endif

Сохрани.

⸻

Шаг 2. Открой s21_string.c

nano s21_string.c

Полностью замени содержимое на это:

#include "s21_string.h"
size_t s21_strlen(const char *str) {
    size_t length = 0;
    if (str != NULL) {
        while (str[length] != '\0') {
            length++;
        }
    }
    return length;
}
int s21_strcmp(const char *str1, const char *str2) {
    int result = 0;
    int i = 0;
    while (result == 0 && str1[i] != '\0' && str2[i] != '\0') {
        if (str1[i] != str2[i]) {
            result = str1[i] - str2[i];
        }
        i++;
    }
    if (result == 0) {
        result = str1[i] - str2[i];
    }
    return result;
}
char *s21_strcpy(char *destination, const char *source) {
    int i = 0;
    while (source[i] != '\0') {
        destination[i] = source[i];
        i++;
    }
    destination[i] = '\0';
    return destination;
}
char *s21_strcat(char *destination, const char *source) {
    int i = 0;
    int j = 0;
    while (destination[i] != '\0') {
        i++;
    }
    while (source[j] != '\0') {
        destination[i] = source[j];
        i++;
        j++;
    }
    destination[i] = '\0';
    return destination;
}
char *s21_strchr(const char *str, int symbol) {
    char *result = NULL;
    int i = 0;
    char target = symbol;
    while (result == NULL && str[i] != '\0') {
        if (str[i] == target) {
            result = (char *)(str + i);
        }
        i++;
    }
    if (result == NULL && target == '\0') {
        result = (char *)(str + i);
    }
    return result;
}

Сохрани.

⸻

Шаг 3. Открой s21_string_test.c

nano s21_string_test.c

Полностью замени содержимое на это:

#include <stdio.h>
#include "s21_string.h"
void s21_strlen_test(void);
void s21_strcmp_test(void);
void s21_strcpy_test(void);
void s21_strcat_test(void);
void s21_strchr_test(void);
void run_strlen_test(const char *input, size_t expected);
void run_strcmp_test(const char *str1, const char *str2, int expected_sign);
void run_strcpy_test(const char *source, const char *expected);
void run_strcat_test(const char *destination_start, const char *source, const char *expected);
void run_strchr_test(const char *str, int symbol, const char *expected);
int main(void) {
    s21_strlen_test();
    s21_strcmp_test();
    s21_strcpy_test();
    s21_strcat_test();
    s21_strchr_test();
    return 0;
}
void s21_strlen_test(void) {
    run_strlen_test("hello", 5);
    run_strlen_test("", 0);
    run_strlen_test("School 21", 9);
    run_strlen_test("a", 1);
    run_strlen_test("12345", 5);
}
void s21_strcmp_test(void) {
    run_strcmp_test("abc", "abc", 0);
    run_strcmp_test("abc", "abd", -1);
    run_strcmp_test("abd", "abc", 1);
    run_strcmp_test("", "", 0);
    run_strcmp_test("abc", "abcd", -1);
    run_strcmp_test("abcd", "abc", 1);
}
void s21_strcpy_test(void) {
    run_strcpy_test("hello", "hello");
    run_strcpy_test("", "");
    run_strcpy_test("School 21", "School 21");
    run_strcpy_test("a", "a");
    run_strcpy_test("12345", "12345");
}
void s21_strcat_test(void) {
    run_strcat_test("hello ", "world", "hello world");
    run_strcat_test("", "abc", "abc");
    run_strcat_test("abc", "", "abc");
    run_strcat_test("School ", "21", "School 21");
    run_strcat_test("1", "2345", "12345");
}
void s21_strchr_test(void) {
    run_strchr_test("hello", 'e', "ello");
    run_strchr_test("hello", 'z', NULL);
    run_strchr_test("hello", 'h', "hello");
    run_strchr_test("hello", 'o', "o");
    run_strchr_test("hello", '\0', "");
    run_strchr_test("", 'a', NULL);
}
void run_strlen_test(const char *input, size_t expected) {
    size_t result = s21_strlen(input);
    printf("strlen Input: \"%s\"\n", input);
    printf("strlen Output: %zu\n", result);
    if (result == expected) {
        printf("strlen Result: SUCCESS\n");
    } else {
        printf("strlen Result: FAIL\n");
    }
}
void run_strcmp_test(const char *str1, const char *str2, int expected_sign) {
    int result = s21_strcmp(str1, str2);
    int success = 0;
    if (expected_sign == 0 && result == 0) {
        success = 1;
    } else if (expected_sign < 0 && result < 0) {
        success = 1;
    } else if (expected_sign > 0 && result > 0) {
        success = 1;
    }
    printf("strcmp Input: \"%s\" \"%s\"\n", str1, str2);
    printf("strcmp Output: %d\n", result);
    if (success) {
        printf("strcmp Result: SUCCESS\n");
    } else {
        printf("strcmp Result: FAIL\n");
    }
}
void run_strcpy_test(const char *source, const char *expected) {
    char destination[100];
    s21_strcpy(destination, source);
    printf("strcpy Input: \"%s\"\n", source);
    printf("strcpy Output: \"%s\"\n", destination);
    if (s21_strcmp(destination, expected) == 0) {
        printf("strcpy Result: SUCCESS\n");
    } else {
        printf("strcpy Result: FAIL\n");
    }
}
void run_strcat_test(const char *destination_start, const char *source, const char *expected) {
    char destination[100];
    s21_strcpy(destination, destination_start);
    s21_strcat(destination, source);
    printf("strcat Input: \"%s\" \"%s\"\n", destination_start, source);
    printf("strcat Output: \"%s\"\n", destination);
    if (s21_strcmp(destination, expected) == 0) {
        printf("strcat Result: SUCCESS\n");
    } else {
        printf("strcat Result: FAIL\n");
    }
}
void run_strchr_test(const char *str, int symbol, const char *expected) {
    char *result = s21_strchr(str, symbol);
    int success = 0;
    if (result == NULL && expected == NULL) {
        success = 1;
    } else if (result != NULL && expected != NULL && s21_strcmp(result, expected) == 0) {
        success = 1;
    }
    printf("strchr Input: \"%s\" '%c'\n", str, symbol);
    if (result == NULL) {
        printf("strchr Output: NULL\n");
    } else {
        printf("strchr Output: \"%s\"\n", result);
    }
    if (success) {
        printf("strchr Result: SUCCESS\n");
    } else {
        printf("strchr Result: FAIL\n");
    }
}

Сохрани.

⸻

Шаг 4. Обнови Makefile

nano Makefile

Полностью замени содержимое на это:

CC = gcc
CFLAGS = -Wall -Wextra -Werror
BUILD_DIR = ../../build
SOURCES = s21_string.c s21_string_test.c
strlen_tests: $(BUILD_DIR)/Quest_6
strcmp_tests: $(BUILD_DIR)/Quest_7
strcpy: $(BUILD_DIR)/Quest_8
strcat: $(BUILD_DIR)/Quest_9
strchr: $(BUILD_DIR)/Quest_10
$(BUILD_DIR)/Quest_6: $(SOURCES) s21_string.h
	mkdir -p $(BUILD_DIR)
	$(CC) $(CFLAGS) $(SOURCES) -o $(BUILD_DIR)/Quest_6
$(BUILD_DIR)/Quest_7: $(SOURCES) s21_string.h
	mkdir -p $(BUILD_DIR)
	$(CC) $(CFLAGS) $(SOURCES) -o $(BUILD_DIR)/Quest_7
$(BUILD_DIR)/Quest_8: $(SOURCES) s21_string.h
	mkdir -p $(BUILD_DIR)
	$(CC) $(CFLAGS) $(SOURCES) -o $(BUILD_DIR)/Quest_8
$(BUILD_DIR)/Quest_9: $(SOURCES) s21_string.h
	mkdir -p $(BUILD_DIR)
	$(CC) $(CFLAGS) $(SOURCES) -o $(BUILD_DIR)/Quest_9
$(BUILD_DIR)/Quest_10: $(SOURCES) s21_string.h
	mkdir -p $(BUILD_DIR)
	$(CC) $(CFLAGS) $(SOURCES) -o $(BUILD_DIR)/Quest_10
clean:
	rm -rf $(BUILD_DIR)
rebuild: clean strlen_tests strcmp_tests strcpy strcat strchr

⸻

Шаг 5. Проверка стиля

clang-format -i *.c *.h
clang-format -n *.c *.h

Если вторая команда ничего не вывела — стиль нормальный.

⸻

Шаг 6. Сборка Quest 10

make strchr

⸻

Шаг 7. Запуск Quest 10

../../build/Quest_10

Во всех тестах должно быть:

Result: SUCCESS

⸻

Шаг 8. Проверка памяти

valgrind --tool=memcheck --leak-check=yes ../../build/Quest_10

В конце должно быть:

All heap blocks were freed -- no leaks are possible
ERROR SUMMARY: 0 errors

После этого проверим git status и решим, делаем бонусы или пушим обязательную часть.