Привести char к массиву char или массив к char? - PullRequest
5 голосов
/ 14 января 2011

Итак, допустим, у меня есть char и я хочу strcat () передать его в массив char в одну строку кода. Для [непрактичного] примера:

strcat("ljsdflusdfg",getchar());

Или я хотел сделать обратное, что будет подходящей функцией для строк concat или typecast, независимо от типа данных? Или, может быть, какой-то синтаксис мне не хватает ...

Вот пример. Компилируется просто отлично, но вылетает.

char* input(){
 char* inp="";
 while(1){
  char c=getchar();
  if(c){
   if(c=='\n'||c==EOF){
    break;
   }else{
    strcat(inp,(char*)c);
   }
  }
 }
 return inp;
}

Ответы [ 8 ]

3 голосов
/ 14 января 2011

strcat обрабатывает свой аргумент как указатель на строку с нулевым символом в конце.Приведение char к char * просто опасно, и я не могу представить себе причин, по которым оно когда-либо будет полезным (не говоря уже о том, что вы глупы, когда пытаетесь это сделать - все делают глупые ошибки, когда учатся. Вот почему мы 'здесь.)

Причина в том, что он будет интерпретировать один байт char плюс дополнительные sizeof(char*) - sizeof(char) (обычно 3) байта, окружающие этот char, как указатель, на который будет указывать... в любом месте.У вас нет возможности узнать, куда он указывает, поскольку 3 из этих байтов находятся вне вашего контроля, и, следовательно, нет способа узнать, указывает ли он на действительные данные.

Вы можете принять это как второй подход:

strcat(inp, &c);

На этот раз вам будет лучше, так как &c является выражением типа char *, и приведение не требуется.Но опять же, strcat предполагает, что его аргумент является строкой с нулевым символом в конце, и, поскольку у вас нет способа гарантировать нулевой байт после данных char, это не сработает.

Лучший способ - этоэто:

size_t len = strlen(inp); // this may already be calculated somewhere else
...
inp[len++] = c; // add c as the last character, and adjust our len
inp[len] = '\0'; // add a new nul terminator to our string

ОБНОВЛЕНИЕ:

На самом деле я солгал. best - это использовать стандартную библиотечную функцию fgets, которая, кажется, выполняет более или менее то, что вы пытаетесь сделать.Честно говоря, я забыл об этом, но если это домашнее задание, ваш профессор может не захотеть, чтобы вы использовали fgets, чтобы вы могли научиться делать это вручную.Однако, если это не домашняя работа, fgets делает именно то, что вы ищете.(На самом деле, третий подход хорошо подходит для реализации функций, подобных fgets или fgets.)

Я бы также добавил несколько других комментариев к вашей функции input:

  1. char* inp = ""; будет указывать на данные только для чтения.Недостаток в стандарте C (для обратной совместимости) позволяет присваивать строковые литералы типам char* вместо типов const char *, как это должно быть (IMHO).

    Есть несколько способов приблизиться к этому, но лучшим является динамическое распределение.Используйте функцию malloc, чтобы зарезервировать некоторые данные, отследите, сколько вы использовали в своей функции, и используйте функцию realloc, если вам понадобится больше места для ее хранения.Если вам нужна помощь с этим, я уверен, что вы вернетесь сюда (надеюсь, не слишком в ближайшее время) с другим вопросом.:)
  2. getchar() возвращает int, поскольку EOF определено как выход за пределы нормального диапазона char.Чтобы различать любые char и EOF, лучше всего сделать c и int.В противном случае совершенно правильный символ может сигнализировать EOF.Обязательно приведите c к char при добавлении его в строку.
2 голосов
/ 14 января 2011

Если вы хотите объединить один char в строку, вы можете использовать strncat() и указать количество символов для объединения как 1. Но учтите, что:

  • В буфере назначения должно быть достаточно места; и
  • В C89 у вас должен быть фактический char объект для получения адреса (чтобы вы не могли напрямую объединить результат getchar().

Например:

char str[5] = "foo";
char c;
int ch;

if ((ch = getchar()) != EOF) {
    c = ch;
    strncat(str, &c, 1);
}

В C99 вы можете использовать составной литерал , и второе ограничение не применяется:

char str[5] = "foo";
int ch;

if ((ch = getchar()) != EOF) {
    strncat(str, &(char){ ch }, 1);
}
2 голосов
/ 14 января 2011
strcat(inp,(char*)c);

То есть пытается объединить содержимое памяти в том месте, где когда-либо находится 'c' (как место в памяти), пока не найдет ноль.

Лучший способ - создать пустую строкулюбого максимального размера, который вы считаете разумным, заполните его нулями, а затем просто вставьте 'c' в текущей последней позиции

1 голос
/ 14 января 2011

Это не сработает, потому что у указателя * inp char нет памяти для его резервного копирования.Когда вы объявили, что это char * inp = "";, вы дали ему только адрес пустой строки.Если бы вы дали следующее объявление char * inp = "abcdefg", то вы могли бы записать в него 7 символов до того, как перезаписали '\ 0' и попали в беду.

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

Кроме того, вашему strcat нужно иметь символ '&' перед символом c.

0 голосов
/ 08 августа 2013

Один простой способ - использовать snprintf:

char newString[50+1];
snprintf(newString, sizeof(newString), "%s%c", "ljsdflusdfg", getchar());

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

Примечания: я использую +1, чтобы напомнить себе, что должно быть место для нулевого завершения, и snprintf лучше, чем sprintf, так как ему задан размер буфера для предотвращения переполнения буфера.

0 голосов
/ 14 января 2011

Преобразование символа в массив символов?
Это все равно, что сказать, что вы хотите бросить символ в строку.
Вы просто не можете сделать это напрямую.
Вместо char поместите его в массив (myChar []).
После этого поместите его в исходный массив символов.

0 голосов
/ 14 января 2011

Ваш код падает, потому что strcat ожидает строки с нулевым символом в конце для обоих своих параметров.

Если вы хотите объединить символ, вам сначала нужно создать из него строку с нулевым символом в конце.

char c[2] = {0,0};
c[0] = getchar();
strcat(inp, c);

Но не используйте strcat , если только вы не можете гарантировать, что во входной строке выделено место для этого дополнительного символа.Лучше для вас strncat, который также включает параметр количества места в первом параметре (dest).

Я рекомендую прочитать this first.

0 голосов
/ 14 января 2011

Во-первых, вы возвращаете указатель на массив, выделенный стеком.Это неопределенное поведение.Во-вторых, вы пытаетесь записать символы в нераспределенную память.В-третьих, тип inp - это const char*, а не char*.

. Вы хотите что-то вроде:

char* input(char *dest) {
  strcpy(dest,"");
  while(1){
  char c=getchar();
  if(c){
   if(c=='\n'||c==EOF){
    break;
   }else{
    strcat(inp,&c);
   }
  }
 }
 return dest;
}
...