Пользовательская функция ввода строки - PullRequest
2 голосов
/ 22 октября 2008

Я читаю книгу K & R и немного застрял.

Что не так со следующим?

void getInput(int* output) {
   int c, i;
   for(i=0; (c = getchar()) != '\n'; i++)
     output[i] = c; // printf("%c", c) prints the c value as expected
   output[++i] = '\0';
}

Когда я запускаю программу, она никогда не выходит из цикла, и мне нужно Ctrl + C , чтобы выйти. Однако, если я заменю пятую строку на printf("%c", c);, она напечатает все входные данные очень хорошо после нажатия Enter и создания новой строки.

Ответы [ 7 ]

7 голосов
/ 22 октября 2008

Что не так со следующим?

1. void getInput(int* output) {

Почему входной аргумент является int *, если вы хотите сохранить массив символов? Вероятно

void getInput(char* output) {

лучше.

Кроме того, как вы узнаете, что указатель вывода указывает куда-то, где у вас достаточно памяти для записи ввода пользователя? Возможно, вы должны указать максимальную длину буфера в качестве дополнительного параметра, чтобы избежать ошибок переполнения буфера, как указано PW .

5.   output[++i] = '\0';

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

output[i] = '\0';

Кроме этих, программа работает нормально и выводит то, что мы вводим до возврата.

FWIW, я проверил это, назвав его так:

 int main(void)
{
    char o[100];
    getInput(o);
    printf("%s", o);
    return 0;
}
1 голос
/ 22 октября 2008

Ваш последний опубликованный код содержит 3 ошибки, которые я вижу:

char* userInput[MAX_INPUT_SIZE];

Должно быть:

char userInput[MAX_INPUT_SIZE+1];

(это уже упоминал Пакс Диабло)

getInput(&userInput);

Должно быть:

getInput( userInput );

Эта последняя ошибка означает, что вы передали getInput адрес внутри стека вызовов. у вас есть перезапись памяти. возможно, один из ваших вызовов getchar () возвращается не по адресу.

1 голос
/ 22 октября 2008

Для меня это выглядит правильно, как написано, за исключением того, что вам не нужно увеличивать i вне цикла. Значение i увеличивается прямо перед выходом из цикла, поэтому оно уже там, где вы хотите.

Убедитесь, что '\ n' на самом деле превращается в c.

Иногда '\ n' отбрасывается как разделитель.

0 голосов
/ 23 октября 2008

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

Любые предложения о том, как можно сделать лучше?

#include <stdio.h>

#define STACK_SIZE 50
#define MAX_INPUT_SIZE 1000
#define FALSE 0
#define TRUE !FALSE

void get_input();
int valid_input();

int main() {
  char user_input[MAX_INPUT_SIZE + 1]; // +1 for the \0

  get_input(user_input);

  if (valid_input(user_input))
    printf("Success\n");
  else
    printf("Error\n");
}

// Functions
void get_input(char* output) {
  int c, i;
  for(i=0; (c = getchar()) != '\n' && c != EOF && i <= MAX_INPUT_SIZE; i++)
    output[i] = c;
  output[i] = '\0';
}

int valid_input(char* input) {
  char stack[STACK_SIZE];
  char c;
  int i = 0;
  int stack_index = -1;

  while ((c = input[i]) != '\0' && i < STACK_SIZE) {
    switch(c){
      case '[': case '(': case '{':
        stack_index++; 
        stack[stack_index] = c;
        break;
      case ']': case ')': case '}':
        if ((c == ']' && stack[stack_index] != '[') ||
            (c == '}' && stack[stack_index] != '{') ||
            (c == ')' && stack[stack_index] != '('))
          return FALSE;

        // decrement the stack's index now that the closing bracket is found  
        stack_index--;
        break;
    }
    i++;
  }

  // stack index should be back where it started
  return (stack_index == -1);
}
0 голосов
/ 22 октября 2008

Вы пробовали использовать отладчик? Вы должны пройтись по коду в GDB или Visual Studio или что вы используете, и посмотреть, что происходит. Вы сказали, что были новичком, так что, возможно, вы еще не учли это - это довольно обычная техника отладки.

0 голосов
/ 22 октября 2008

Вот полная программа с парой обновлений от вашего ввода, но она все равно не выйдет из цикла. Кстати, это было упражнение 1-24 на стр 34

#include <stdio.h>

#define STACK_SIZE 50
#define MAX_INPUT_SIZE 1000
#define FALSE 0
#define TRUE 1

void getInput();
int validInput();

int main() {
  char* userInput[MAX_INPUT_SIZE];

  getInput(&userInput);

  if (validInput(&userInput) == TRUE)
    printf("Compile complete");
  else
    printf("Error");
}

// Functions
void getInput(char* output) {
  int c, i;
  for(i=0; (c = getchar()) != '\n' && c != EOF && i <= MAX_INPUT_SIZE; i++)
    output[i] = c;
  output[i] = '\0';
}

int validInput(char* input) {
  char stack[STACK_SIZE];
  int c;
  int j;

  for (j=0; (c = input[j]) != '\0'; ) {
    switch(c){
      case '[': case '(': case '{':
        stack[j++] = c;
        break;
      case ']': case ')': case '}':
        if (c == ']' && stack[j] != '[')
          return FALSE;
        else if (c == '}' && stack[j] != '{')
          return FALSE;
        else if (c == ')' && stack[j] != '(')
          return FALSE;

        // decrement the stack's index  
        --j;
        break;
    }
  }

  return TRUE;
}
0 голосов
/ 22 октября 2008

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

...