2016-11-09 5 views
2

Я написал такую ​​программу, которая предполагает возврат строк, содержащих не менее 11 символов и 4 цифры. Я перепутал что-то с типами переменных, я думаю, но я не могу понять, как мне исправить это.Отображение строк с заданным количеством символов

#include <stdio.h> 
#include <ctype.h> 
#include <string.h> 


int main() 
{ 
    char line[200]; 
    char *temp[200]; 
    int i = 0, k=0; 

    printf("Enter a string: \n"); 
    while(fgets(line, sizeof(line),stdin)) 
    { 
     int numberAlpha = 0; 
     int numberDigit = 0; 
     int i; 
     for(i=0; i<strlen(line); i++){ 
      if(isalpha(line[i])) numberAlpha++; 
      else if(isdigit(line[i])) numberDigit++; 
     } 

     if(numberAlpha+numberDigit>10 && numberDigit>3){ 
      temp[i]=line; 
      i++; 
     } 
    } 
    while(temp[k]!='\0'){ 
     printf("%s", temp[k]); 
     k++; 
    } 
    return 0; 
} 
+1

Вы не скопировали успешную строку, только указатель. К сожалению, строка, на которую он указывает, перезаписывается на следующей строке. Посмотрите на 'strdup'. –

ответ

1

Проблема заключается в том вы назначаете адрес же здесь:

temp[i]=line; 

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

Вместо этого, вы можете использовать strdup() (функция POSIX):

temp[i] = strdup(line); 

скопировать строки, которые вы заинтересованы в Если strdup() не доступен, то вы можете использовать malloc() + strcpy() сделать то же самое.. Плюс, free() их позже.

Кроме того, следует помнить, что:

  • fgets() прочтет в символ новой строки, если есть место в буфере, который не может быть то, что вы хотите. Итак, вам нужно обрезать его. Вы можете сделать это с:

    line[strcspn(line, "\n")] = 0; /* trim the trailing newline, if any */ 
    
  • Аргументы в isalpha() и isdigit() должен быть приведен к unsigned char, чтобы избежать возможного неопределенного поведения, т.е. эти две строки:

    if(isalpha(line[i])) numberAlpha++; 
    else if(isdigit(line[i])) numberDigit++; 
    

    должен быть

    if(isalpha((unsigned char)line[i])) numberAlpha++; 
    else if((unsigned char)isdigit(line[i])) numberDigit++; 
    
+0

Хорошо, я получил это, спасибо. Есть ли другой способ написать эту программу, которая не потребует такой «причудливой» функции? – NouName

+0

Если вам не нужно «помнить» эти строки, вы можете избежать копирования, распечатав сразу же внутри цикла. т. е. вы можете заменить w temp [i] = line; 'с' printf ("% s \ n", строка); '. –

+0

Итак, я внес изменения в соответствии с вашими предложениями, но теперь он, кажется, падает после возвращения первой строки, которая следует за оператором if. – NouName

1

Вы повторно используете то же самое буфера каждый раз, и вы сохраняете указатель на этот буфер в массиве temp. То, что вы собираетесь в конечном итоге, это куча одного и того же указателя в этом массиве, указатель которого указывает на последнюю строку в файле.

Что вы можете сделать вместо этого, чтобы переписать temp[i]=line заявления в следующем:

temp[i] = malloc(sizeof(line)) 
memcpy(temp[i], line, sizeof(line)) 

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

Обратите внимание, что, поскольку вы распределения, что в куче, в конце вашей функции вы хотите, чтобы освободить его:

while (temp[k] != '\0') { 
    printf(...); 
    free(temp[k]); 
    k++ 
} 
1

Как было сказано ранее, одна проблема с копированием
темп [I] = линия;
Это можно решить, выполнив новое распределение кучи и сделав memcopy для temp. Другая проблема, которую я мог видеть, - со значением переменной i. Тогда массив temp всегда будет присвоен индексу strlen (line). Возможно, вы думаете о сохранении в массиве temp из 0. Что не происходит.
Этой проблемы можно решить каждый конкретный

int start_index=0; 
while(...){ 
if(numberAlpha+numberDigit>10 && numberDigit>3){ 
     temp[start_index]=line; 
     start_index++; 
    } 
} 
Смежные вопросы