2012-01-27 5 views
0

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

У меня есть Loop в методе makeLower, который, кажется, проходит часть первой итерации цикла while, а затем EXE сбой. Любые советы были бы замечательными, спасибо!

Выход:

C:\Users\Mark\Documents\Visual Studio 2010\Projects\Project 1\Debug>"Project 1.e 
xe" ez.txt 

Line is #draw a diamond ring 

Character is # 

Тогда ошибка "проект 1.exe перестал работать"

Код:

void makeLower(char *input[]){ 
    int i = 0; 
    printf("Line is %s\n", *input); 

    while(input[i] != "\0"){ 
     printf("Character is %c\n", *input[i]); 
     if(*input[i] >= 'A' && *input[i] <= 'Z'){ 
      *input[i] = tolower(*input[i]); 
     } 
     i++; 
    } 

} 

int main(int argc, char *argv[]) { 
    FILE *file = fopen(argv[1], "r"); 
    char linebyline [50], *lineStr = linebyline; 
    char test; 

    glutInit(&argc, argv); 

    while(!feof(file) && file != NULL){ 
     fgets(lineStr , 100, file); 
     makeLower(&lineStr); 
     printf("%s",lineStr); 

     //directFile(); 

    } 
    fclose(file); 


    glutMainLoop(); 
} 
+0

Вы пытались запустить его в отладчике? Кроме того, я могу дать вам подсказку: знаете ли вы, что делает оператор указателя указателя ('*'), например, в выражении '* input [i]'? Я предлагаю вам посмотреть на все это. :) –

+0

Разве это не смеет переменную? Так как он был передан в функцию по ссылке? Я не очень хорош с C tbh. – meriley

+1

Если у вас есть строка (указатель на 'char'), вы можете получить один символ с помощью' string [i] 'где' i' - число от 0 до длины строки минус единица или '* (строка + i) '. Последнее на самом деле то, что компилятор переводит 'string [i]' to. –

ответ

3

Я вижу больше проблем, поэтому я выражаю свои комментарии к ответу:

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

При передаче строки C в функцию вам не нужно передавать адрес указателя на строку (&lineStr), фактический указатель или массив в порядке. Это означает, что вы можете изменить функцию makeLower на void makeLower(char *input) или void makeLower(char input[]). Прямо сейчас аргумент makeLower объявлен как указатель массива или символа, а не указатель на массив символов.

В новом makeLower я предложил выше, вы можете получить доступ к отдельным символам или как массив (input[i]) или в качестве указателя плюс смещение (*(input + i). Как я уже сказал в своем комментарии, последняя версия, что компилятор может создать . если вы используете первый Но первый является более удобным для чтения, так что я предлагаю, что

Также в makeLower вы делаете сравнение с "\0", который является строка, а не символ Это почти прямо на самом деле:.. вы должны использовать input[i] != '\0' .

И, наконец, вот как я его реализую:

void makeLower(char *input) 
{ 
    while (*input != '\0') /* "while (*input)" would also work */ 
    { 
     *input = tolower(*input); 
     input++; 
    } 
} 

Несколько объяснений по поводу функции:

  • Все символьные массивы могут быть преобразованы в указатель полукокса, а не наоборот. Передача указателя char является наиболее распространенным способом передачи строки на самом деле, как вы можете видеть из всех стандартных функций, которые принимают строки (например, strlen или strcpy.)
  • Выражение *inputdereferences (т. Е. Принимает значение указателя на строку). Это то же самое, что и *(input + 0), и поэтому получите значение первого символа в строке.
  • В то время как первый символ в строке не '\0' (что технически является нормальным нулем), мы будем циклически.
  • Получите первый символ строки и передайте ее функции tolower. Это будет работать независимо от того, каков персонаж, tolower вернет только символы верхнего регистра в нижний регистр, все остальные символы будут возвращены так, как они уже были.
  • Результат tolower копируется поверх первого символа. Это работает, потому что перед назначением должна быть выполнена правая сторона задания, поэтому никаких ошибок или проблем не возникнет.
  • Последнее мы увеличиваем указатель на один. Это приведет к тому, что input будет указывать на следующий символ в строке. Это работает, потому что input является локальной переменной, поэтому операции над указателем не будут влиять на что-либо в вызывающей функции.

Эта функция в настоящее время можно назвать так:

char input[100]; 
fgets(input, sizeof(input), stdin); 
printf("before: \"%s\"\n", input); 
makeLower(input); 
printf("after : \"%s\"\n", input); 
+0

Im довольно ужасно на C, когда дело касается ссылок и т. Д. Ваше сообщение решило мою проблему и было суперпопулярным! С этим объяснением я не думаю, что у меня были проблемы с переходом по ссылке. Особенно со струнами. Спасибо. – meriley

0

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

+0

То, что это первая итерация, даже не заканчивается. Символ # - это только первый символ линии. Следующий вывод должен сказать «Character is d» – meriley

+0

Тогда я думаю, что Joachim, вероятно, прав, потому что я знаю в C++, используя нотацию оператора массива, автоматически разыгрывает указатель. – emschorsch

1

Вы пытались использовать (* input [i]! = "\ 0") вместо того, что у вас есть? По какой-то причине вы, похоже, передаете своей функции указатель на указатель на char (* input []) и & lineStr, поэтому было бы разумно разыменовать дважды, когда вы проверите символ символа строки «\ 0» ....

Просто мысль, надеюсь, что это помогает

0

Насколько я понимаю, то, что это хорошо, чтобы передать «\ 0» в tolower(). Это действительное значение unsigned char, и tolower() просто возвращает входной символ, если он не в состоянии сделать какое-либо преобразование.

Таким образом, цикл может быть сжато кладется как:

while(input[i] = tolower(input[i])) 
    ++i; 

Это делает еще один вызов tolower(), но короче и (IMO) вполне понятно. Просто хотел упомянуть об этом в качестве альтернативы.