Манипулирование строками и преобразование

Для упражнения я могу взять два целых числа или две строки. Если мне нужны целые числа в качестве входных данных, мне нужно преобразовать их в строки, а если я беру строки в качестве входных данных, мне нужно преобразовать строки в целые числа. Когда я хочу ввести две строки одновременно, они каким-то образом объединяются. Если я беру целые числа и хочу преобразовать их с помощью snprintf, строки снова объединяются!

Когда я беру строки в качестве входных данных:

#include <stdio.h>
int main(){

    char n[5],m[5];
    scanf("%s %s",n,m);
    printf("%s %s\n",n,m);
}

Ввод: 12345 56789.

но вывод: 1234556789 12346

сканер считает, что «12345 56789» — это целая строка.

Как это происходит? Разве я не указал, что n может содержать только 5 символов? Если я уменьшу n[5] до n[1], результат будет 156789 56789

Когда я беру целые числа в качестве входных данных и пытаюсь преобразовать их с помощью snprintf:

#include <stdio.h>
#include <stdlib.h>
int main(){
    
    int g,w,cnt=0;
    
    scanf("%d %d",&g,&w);
    
    char n[5], m[5];
    snprintf(n,6,"%d",g);
    snprintf(m,6,"%d",w);
    printf("%s\n",n);
    printf("%s\n",m);
}

Если я введу 12345 67894 Выход: 1234567894 67894.

Та же проблема, что и раньше. Что я могу сделать, чтобы решить эту проблему?

В массивах недостаточно места для нулевого символа, обозначающего конец.

Eric Postpischil 25.08.2024 16:58

Спасибо, сэр. Я не знал о важности этого. Теперь это работает. @EricPostpischil

stup 25.08.2024 16:59

Использование %s в scanf опасно, если вы не ограничите его количеством символов, которые у вас есть в массиве минус 1 (чтобы оставить место для нулевого терминатора), поэтому scanf("%s %s",n,m) должно быть scanf("%4s %4s",n,m)

Ted Lyngmo 25.08.2024 17:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
3
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

При определении массива символов для хранения строки в C вы должны учитывать конец символа строки (\0), который scanf неявно помещает в массив. Итак, если вы определите char[5], вы сможете хранить строку, состоящую из 4 символов, поскольку последняя позиция массива используется для \0.

попробуйте изменить свой код следующим образом:

#include <stdio.h>
int main(){

char n[6],m[6];
scanf("%s %s",n,m);
printf("%s %s\n",n,m);
}

Спасибо. Теперь это работает. Я не знал о важности этого. Я думал это автоматически. @N3tMaster

stup 25.08.2024 17:10

Это все еще небезопасно. Если пользователь вводит 123456 123456, его поведение будет неопределенным, поскольку запись будет за пределами границ.

Ted Lyngmo 25.08.2024 17:12

Здесь есть несколько проблем:

  1. Чтобы сохранить строку из 5 символов, вам нужен массив char минимум из 6 элементов, потому что вы должны сохранить 1 дополнительный char для нулевого завершения.

    Следовательно, n и m должны быть:

    char n[6],m[6];
    
  2. Как упоминалось @TedLyngmo, использование scanf для строк так, как вы это делали, небезопасно (даже после фиксации размеров массива) и вызывает неопределенное поведение, если пользователь вводит более 5 символов в строку (из-за записи -за пределы).

    Чтобы это исправить, вам следует использовать scanf со спецификатором ширины:

    Если используется спецификатор ширины, он соответствует ширине или до первого символа пробела, в зависимости от того, что появится первым.

    Это делается следующим образом:

    //------v---v--------
    scanf("%5s %5s",n,m);
    
  3. Хорошая практика требует всегда проверять возвращаемое значение от scanf, чтобы убедиться, что оно выполнено успешно. Он возвращает:

    Количество успешно назначенных аргументов приема

    В вашем случае в случае успеха должно быть 2.

Полный фиксированный пример для вашего первого фрагмента:

#include <stdio.h>
#include <cstdlib>

int main() {

    char n[6], m[6];
    if (scanf("%5s %5s", n, m) != 2) {
        // Handle error ...
        return EXIT_FAILURE;
    }
    printf("%s %s\n", n, m);
}

Что касается вашего второго фрагмента, соответствующие проблемные проблемы указаны выше 1 и 3 (размеры массива символов и проверка возвращаемого значения из scanf).

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