2015-01-08 2 views
0

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

Прямо сейчас, последний способ я пытался добиться этого с динамически выделяемым массивом, так как я не знаю, что пользователь может захотеть ввести, и вот как я делаю, что:

char *process; 
process = (char *)malloc(sizeof(char) * (i+1)); 

я затем, чтобы запросить ввод пользователя и подтвердить ввод с printf:

printf("Enter process name: "); 
scanf("%79s", &process); // take input, load into array 
// fgets(process, sizeof(ARRAY_SIZE), stdin); 
printf("You entered: %s\n", process[i]); 

Я попытался как scanf() и fgets(), где scanf() на самом деле работает и fgets() заставляет Программа для перехода полностью мимо моего printf заявление и идет к этому:

for(i = 0; i < ARRAY_SIZE; i++) 
    printf("process = %s\n", process[i]); 

который является, где программа завершается с Segmentation Fault. Я понимаю, что это связано с тем, что пользовательский ввод перекрывает выделенный буфер.

В gdb при печати значения процесса он заполняется мусором (который из моего понимания - это то, как C инициализирует массив до добавления значений). Сразу после scanf("%79s", &process) процесс показывает, что мой вход добавлен в начале мусора вместо замены мусора. Мой вопрос заключается в том, как я «пустым» массивом, поэтому я отказываюсь от обхода буфера? В течение трех дней пробовал несколько методов, и я думаю, что это связано с тем, что я не хватает некоторых деталей того, как правильно инициализировать мой массив. У меня есть #define ARRAY_SIZE 80, который должен быть более чем достаточным для его функционирования, хотя этого может и не хватить в последующих реализациях.

Любая помощь очень ценится.

+0

Вы должны сказать нам, что 'i' и его значение, но еще' Scanf ("% 79s", и процесс); 'является неверно и должно быть 'scanf («% 79s », process);' – ouah

+0

У вас есть кусочки кода, которые выглядят неправильно. Вы должны отправить сообщение [MCVE] (http://stackoverflow.com/help/mcve). Это будет полезно для всех, чтобы увидеть, что и где ваш код не совсем прав. –

+0

Я инициализировал 'i' как' i = ARRAY_SIZE; '. Почему я должен делать 'scanf («% 79s », process)' в отличие от моей исходной версии? Я думал, что хочу загрузить вход в начальный адрес 'process'. Я собираюсь собрать MCVE для вас, ребята, поскольку у меня есть несколько других функций, которые отлично работают в программе, но делают это довольно долго. – TomJ

ответ

2

Переменная process уже указатель, &process имеет тип char** и представляет собой указатель на переменную указатель, а не указатель на выделенный буфер.

sizeof(char) всегда равен 1 по определению, поэтому нет необходимости в вызове malloc(). Если вы используете scanf() это должно быть так:

scanf("%79s", process) ; 

но поскольку длина жестко закодированы в строке, и не имеет отношения ни i или ARRAY_SIZE, то лучше использовать fgets(), но вы используете длину аргумента sizeof(ARRAY_LEN) который то же самое, что и sizeof(int); вы имели в виду только ARRAY_LEN. В этом случае распределение не должно быть, потому что i + 1fgets() вставляет NUL в пределах размера данной, так что:

fgets(process, ARRAY_SIZE, stdin) ; 

Более того, вряд ли нужно использовать malloc() для массива фиксированной длины; вы не устанавливаете массив для ввода ввода, а ограничиваете вход для соответствия массиву.В таком случае я хотел бы предложить:

char process[ARRAY_SIZE] ; 
printf("Enter process name: ") ; 
fgets(process, sizeof(process), stdin) ; 

Для вывода входных данных символов по-характеру, вам нужен формат %c спецификатора, а не %s:

for(i = 0; i < ARRAY_SIZE; i++) 
    printf("process = %c\n", process[i]) ; 

, но что будет печатать неиспользованные, unitialised символов из массива, так что более вероятно:

for(i = 0; process[i] != '\0'; i++) 
    printf("process = %c\n", process[i]) ; 

или с момента process является завершенным нуль строки, с означают:

printf("process = %s\n", process) ; 

Так в конечном счете, все, что вам нужно:

char process[ARRAY_SIZE] ; 
printf("Enter process name: ") ; 
fgets(process, sizeof(process), stdin) ; 
printf("process = %s\n", process) ; 
+0

красиво. который работал как шарм. У меня возникло недоразумение в том, как фактически получить данные из 'stdin' в массив, и это прекрасно ответило. Спасибо @Clifford, вы многое разъяснили мне. – TomJ

0
#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    char *process; 
    int i = 0;//number of input character; 
    size_t size;//Allocated size 
    int ch; 

    //process = (char *)malloc(sizeof(char) * (i+1));//+1 for '\0' 
    size = 16;//Initial size 
    process = malloc(size);//cast don't need in C 

    printf("Enter process name: ");//fflush(stdout); 
    while((ch = getchar())!=EOF && ch != '\n'){ 
     if(i == size -1){//-1 for NUL('\0') 
      char *temp = realloc(process, size += 16);//expand size 
      if(temp==NULL){ 
       fprintf(stderr, "failed to malloc\n"); 
       free(process); 
       exit(EXIT_FAILURE); 
      } 
      process = temp;//successfully extended update 
     } 
     process[i++] = ch; 
    } 
    process[i] = 0; 
    printf("process = %s\n", process);//type of process[i] is `char` 
    free(process); 
    return 0; 
} 
Смежные вопросы