C, имеющий дело со строкой переменной длины

Я новичок в C, учусь в университете. В одном из заданий я имею дело со струнами. Я беру строки, введенные пользователем или извлеченные из файла, а затем использую для них функцию для получения ответа (если существует определенное качество).

Строка может быть переменной длины, но допустимо предположить, что ее максимальная длина составляет 80 символов.

Я создал программу, используя

char s[81];

а затем каждый раз заполнять один и тот же массив разными строками. Поскольку строка должна оканчиваться нулем, я просто добавил '\ 0' в индекс 80;

s[80] = '\0';

Но потом у меня появилось много странного поведения - несвязанные символы в конце введенной мной строки. Я предположил, что это связано с тем, что между концом «настоящих» символов и символом «\ 0» был пробел, заполненный мусором (?).

Итак, я создал функцию:

void clean_string(char s[], int string_size) {
    int index = 0;
    while(index < string_size) {
        s[index++] = '\0';
    }
}

То, что я называю чистым, - это просто заполнение строки нулями. Я делаю это каждый раз, когда заканчиваю работать со строкой и готов принять новую. Затем я снова заполняю строку символом за символом, и когда я когда-нибудь остановлюсь, следующий символ обязательно будет '\ 0'. Чтобы не включать в код магические числа (81 каждый раз, когда я вызываю clean_string), я использовал следующее:

#define STRING_LENGTH 81

Это подходит для меня. Струны не показывают странного поведения. Но мне было интересно, считается ли это плохой практикой. Есть ли проблемы с таким подходом? Подчеркиваю, я прошу не о помощи в самом задании, а о том, как лучше подходить к подобным ситуациям.

Зависит от того, как вы набираете свои струны. Если вы используете строковую функцию, такую ​​как strcpy или strcat, то записываемая ими строка уже будет завершена нулем.

Blaze 25.10.2018 14:44

Вы просто делаете лишнюю ненужную работу (80 байт - это не так уж много; представьте, что у вас есть строки длиной 16 Мбайт!). Легко отслеживать последний действительный символ и при необходимости добавлять '\0'.

pmg 25.10.2018 14:46

Все подпрограммы обработки строк стандартной библиотеки C, такие как strcpy, завершают строку символом '\0', кроме strncpy, и распознают первый нулевой символ как конец строки.

Paul Ogilvie 25.10.2018 14:46

Почему вы не можете просто установить завершающий 0 в точке, где вы поместили последний прочитанный символ в массив, и вы точно знаете, где вы оказались? Если это невозможно и вы хотите заполнить массив нулями, я бы не стал использовать функцию и цикл, я бы просто использовал memset(s, 0, string_size).

lurker 25.10.2018 14:46

@Blaze Я использую getchar для чтения строки по символу за раз, пока не встретится новая строка.

Nexaspx 25.10.2018 14:47

@Nexaspx: в вашей функции с помощью getchar() реализуйте текущий счетчик. В конце просто выполните s[runningcount] = 0; (и, возможно, верните runningcount вызывающему абоненту).

pmg 25.10.2018 14:49

@PaulOgilvie Я читаю строку по символам. Есть ли еще толк от strcopy? Я никогда не использовал его, но из того, что я вижу, он принимает строку, а я имею дело с потоком символов. Нужно ли мне использовать какую-то другую функцию для чтения строки?

Nexaspx 25.10.2018 14:53

@pmg Я только что попробовал, и, конечно, это работает. Не знаю, зачем я это усложнял :)

Nexaspx 25.10.2018 14:56

Вы можете использовать fgets.

Paul Ogilvie 25.10.2018 15:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
781
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вместо того, чтобы предварительно заполнять весь массив нулями, должно быть просто добавить один ноль после того, как вы прочитали все соответствующие символы.

Например:

char s[STRING_LENGTH];
int c;
int idx = 0;

while (((c = getchar()) != '\n') && (idx < STRING_LENGTH - 1) && (c != EOF)) {
    s[idx++] = c;
}
s[idx] = 0;

Я думаю, что использовать s [idx] = 0 или s [idx] = '\ 0' - дело вкуса. Здесь есть обсуждение: stackoverflow.com/questions/16955936/…

manoliar 25.10.2018 15:49
(idx < STRING_LENGTH - 1) до ((c = getchar()) != '\n') позволяет избежать потери данных. Если места недостаточно, просто оставьте stdin непрочитанным. Тем не менее, не имеет большого значения с OP, «предположим, что их максимальная длина составляет 80».
chux - Reinstate Monica 25.10.2018 20:04

Другие вопросы по теме