2015-12-10 5 views
2

Я хочу прочитать в первых 20 символах от stdin. Смогу ли я использовать цикл for, который повторяется 20 раз и scanf("%c",&var)? Что произойдет, если длина ввода меньше 20 символов?Итерация через строку из stdin в C

Я думал об использовании gets(), чтобы обойти эту проблему. Прочитайте всю строку, затем повторите по строке до тех пор, пока счетчик не достигнет 20 или не будет достигнут конец строки. Однако есть ли способ обнаружить конец строки?

Или есть лучший способ?

Только прошу об этом, потому что нам не разрешено использовать какие-либо функции из библиотеки string.h.

+1

Не могли бы вы показать нам, что вы пробовали до сих пор? –

+0

прочитайте на буферизованном входе, он будет на вашем пути –

+1

Если длина ввода меньше 20 символов, 'scanf()' вернет '0', когда вы пройдете мимо конца. – Barmar

ответ

1

Вы можете попробовать этот путь ...

1 - прочитать первые 20 символов строки с помощью зсапЕ(), как показано в примере, приведенном ниже в массиве символов.

, например:

char str[21]; 

    scanf("%20[^\n]s",str); 

2 - Наконец-то вы будете иметь первые 20 символов из строки в массиве вашего персонажа.

3 - если длина строки меньше 20, то она автоматически назначит символ «\ 0» в конце строки.

и если вы хотите, чтобы найти общее количество символов в массиве затем вычислить длину массива

** Конец струны определяют с помощью «\ 0» NULL символ

+3

[Не использовать 'gets' для чтения ввода.] (Http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be -used) – Holt

+0

@holt, почему ты так говоришь? – Nutan

+0

Поскольку 'get' не безопасен, он будет читать все до символа' \ n', то есть ваш буфер достаточно длинный, чтобы его сохранить или нет. Есть много сообщений на SO (ссылка, которую я разместил, одна) и другие сайты, объясняющие, почему вы не должны использовать 'gets'. – Holt

1

Вот решение, используя основной fgetc:

#include <stdio.h> 

#define LEN(arr) ((int) (sizeof (arr)/sizeof (arr)[0])) 

static void ReadLine(FILE *file, char result[], int resultLen) 
{ 
    int i, ch; 

    ch = fgetc(file); 
    i = 0; 
    while ((ch != EOF) && (ch != '\n') && (i < resultLen - 1)) { 
     result[i] = ch; 
     ch = fgetc(file); 
     i++; 
    } 
    result[i] = '\0'; 
} 


int main(void) 
{ 
    char s[20 + 1]; 

    ReadLine(stdin, s, LEN(s)); 
    puts(s); 
    return 0; 
} 
+0

Как насчет этого? «не разрешено использовать какие-либо функции из библиотеки string.h». – sestus

+0

@sestus OK, я не использую * strlen * сейчас. –

+0

EOF - это int, и вы не должны сравнивать его с символом. На некоторых платформах этот код будет работать навсегда. –

0

Вот короткая версия, которая работает с использованием scanf:

#include <stdio.h> 

int main(void) { 
    char buffer[20 + 1] ; // 20 characters + 1 for '\0' 
    int nread ; 
    nread = scanf("%20[^\n]", buffer) ; // Read at most 20 characters 
    printf("%s\n", buffer); 
    return 0; 
} 

scanf автоматически добавит '\0' символ в нужном месте в buffer и с "%20[^\n]" он будет читать в большинстве 20 символов, отличных от '\n'.

Если вы хотите поместить это в функции и избежать повторений 20 (ошибки):

#include <stdio.h> 

int read_chars (char buffer[], int len) { 
    char format[50] ; 
    sprintf(format, "%%%d[^\n]", len); 
    return scanf(format, buffer) ; 
} 

#define MAX_CHARS 20 

int main(void) { 
    char buffer[MAX_CHARS + 1] ; // 20 characters + 1 for '\0' 
    read_chars (buffer, MAX_CHARS) ; 
    printf("%s\n", buffer); 
    return 0; 
} 

Edit: Если вы не хотите использовать sprintf создать строку формата, вы могли бы использовать препроцессор (не будет работать, если MAX_CHARS не препроцессор константа):

#include <stdio.h> 

#define _READ_CHARS(buffer, N) scanf("%" #N "[^\n]", buffer) 
#define READ_CHARS(buffer, N) _READ_CHARS(buffer, N) 

#define MAX_CHARS 20 

int main(void) { 
    char buffer[MAX_CHARS + 1] ; // 20 characters + 1 for '\0' 
    READ_CHARS (buffer, MAX_CHARS) ; 
    printf("%s\n", buffer); 
    return 0; 
} 
+0

Насколько я понимаю, невозможно написать общую функцию чтения строк с помощью * scanf *, поскольку спецификатор ширины не может быть изменен, или я ошибаюсь? –

+0

@AugustKarlstrom См. Мое редактирование, вы можете создать строку формата «на лету», вам просто нужно быть осторожным в отношении длины строки 'format' (в этом случае я предположил, что в этом случае достаточно 50). – Holt

+0

Я вижу, хороший момент. –

0

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

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

    int main(){ 
     //Declare the reading buffer. Need 1 more position to add '\0' 
     char buffer[21]; 

     int char_num; 
     if ((char_num = read(0, buffer, 20)) < 0) { 
      perror("read: "); 
      exit(1); 
     } 
     //means that there were less than 20 chars in stdin 
     //add the null character after the last char and return 
     else if (char_num < 20) { 
      //terminate the string after the last char read from stdin 
      buffer[char_num] = '\0'; 
      close(0); 
      printf("%s\n", buffer); 
     } 
     //means that there were more than 20 (or exactly 20 chars on stdin) 
     else { 
      buffer[20] = '\0'; 
      printf("%s\n", buffer); 
      //now it depends on what you want to do with the remaining chars 
      //this read just discard the rest of the data, in the same buffer 
      //that we ve used. If you want to keep this buffer for some other 
      //task, figure out some other solution 
      while(1) { 
       if ((char_num = read(0, buffer, 20)) < 0) { 
        perror("read: "); 
        exit(1); 
       } 
       close(0); 
       if (char_num == 0 || char_num < 20) 
        break; 
      } 
     } 
     return 0; 
    } 
Смежные вопросы