Устранение предупреждений лязга в простом C сканере - PullRequest
0 голосов
/ 17 февраля 2020

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

#include <stdio.h>

char* scanFile(FILE *fl, char* ch);

int main(int argc, char const* argv[])
{
    FILE *file;
    char *ch = "\0";

    ch = scanFile(file, ch);
    fclose(file);

    printf("%s\n", ch);
    return 0;
}

char* scanFile(FILE *fl, char* ch)
{
    fl = fopen("/tmp/test.txt", "r");
    if (fl)
    {
        while ((ch = getchar()) != EOF) { putchar(ch); }
    }

    return ch;
}

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

clang scanFile scanFile.c 
scanFile.c:22:20: warning: incompatible integer to pointer conversion assigning to 'char *'    
from 'int' [-Wint-conversion]
    while ((ch = getchar()) != EOF) { putchar(ch); }
               ^ ~~~~~~~~~
scanFile.c:22:33: warning: comparison between pointer and integer ('char *' and 'int')
    while ((ch = getchar()) != EOF) { putchar(ch); }
           ~~~~~~~~~~~~~~~~ ^  ~~~
scanFile.c:22:51: warning: incompatible pointer to integer conversion passing 'char *' to parameter of type 'int' [-Wint-conversion]
    while ((ch = getchar()) != EOF) { putchar(ch); }
                                              ^~
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/stdio.h:172:17: note: passing argument to parameter here
int      putchar(int);
                ^
3 warnings generated.
ld: can't link with a main executable file 'scanFile' for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Однако, поскольку в процессе компиляции отсутствуют какие-либо серьезные ОШИБКИ, при запуске исполняемого файла, сгенерированного в результате моей вышеупомянутой компиляции, на экране появляется следующее (следующий faux-latin это файл, который должен быть прочитан и выведен так же, как в моем C коде.)

Ergo ego senator inimicus, si ita vultis, homini, amicus esse, sicut semper fui, rei publicae debeo. 
Quid? si ipsas inimicitias, depono rei publicae causa, quis me tandem iure reprehendet, praesertim cum ego omnium meorum consiliorum atque factorum exempla semper ex summorum hominum consiliis atque factis mihi censuerim petenda.

Eodem tempore etiam Hymetii praeclarae indolis viri negotium est actitatum, cuius hunc novimus esse textum. 
Cum Africam pro consule regeret Carthaginiensibus victus inopia iam lassatis, ex horreis    
Romano populo destinatis frumentum dedit, pauloque postea cum provenisset segetum copia, integre sine ulla restituit mora.

Et hanc quidem praeter oppida multa duae civitates exornant Seleucia opus Seleuci regis, et Claudiopolis quam deduxit coloniam Claudius Caesar.
Isaura enim antehac nimium potens, olim subversa ut rebellatrix interneciva aegre vestigia claritudinis pristinae monstrat admodum pauca.
[1]    59823 segmentation fault  ./scanFile

ПРИМЕЧАНИЕ: НО ЭТО ТАКЖЕ ДАЕТ '59823 ошибка сегментации ./scanfile' ошибка все еще.

ДОПОЛНИТЕЛЬНО: лязг-стена дает;

C clang -Wall scanFile.c 
scanFile.c:10:19: warning: variable 'file' is uninitialized when used here [-Wuninitialized]
    ch = scanFile(file, ch);
              ^~~~
scanFile.c:7:15: note: initialize the variable 'file' to silence this warning
    FILE *file;
          ^
               = NULL
scanFile.c:22:20: warning: incompatible integer to pointer conversion assigning to 'char *' from 'int' [-Wint-conversion]
    while ((ch = getchar()) != EOF) { putchar(ch); }
               ^ ~~~~~~~~~
scanFile.c:22:33: warning: comparison between pointer and integer ('char *' and 'int')
    while ((ch = getchar()) != EOF) { putchar(ch); }
           ~~~~~~~~~~~~~~~~ ^  ~~~
scanFile.c:22:51: warning: incompatible pointer to integer conversion passing 'char *' to parameter of type 'int' [-Wint-conversion]
    while ((ch = getchar()) != EOF) { putchar(ch); }
                                              ^~
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/stdio.h:172:17: note: passing argument to parameter here
int      putchar(int);
                ^
4 warnings generated.

1 Ответ

0 голосов
/ 17 февраля 2020

Ахмет, у вас есть несколько ошибок в вашем коде:

  • Вы не выделяете память для результирующей строки. Когда вы определяете строку, как вы делаете char *ch = "\0";, она называется string literal. Попытка изменить строковый литерал - неопределенное поведение. Вы можете прочитать больше о строковых литералах здесь здесь . Это вызывает ошибку сегментации.
  • Вы пытаетесь передать указатель файла в функцию scanFile, чтобы закрыть файл после завершения функции. Но когда вы передаете указатель файла в функцию scanFile, он передается по значению. И компилятор предупреждает вас, что вы не инициализировали его перед передачей. Когда функция scanFile открывает файл и присваивает результирующий указатель файла своему параметру, он не может быть доступен вне функции. Вы должны вернуть указатель файла, чтобы сделать это.
  • Вы используете getchar для чтения символа из файла. Используется для получения персонажа из stdin. По умолчанию он получает символы с клавиатуры. Вы должны использовать fgetc, чтобы получить символ из файла.

Вот рабочий пример для вас, который ОБНОВЛЕН для проверки errno для возможных malloc или fopen ошибка:

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

#define MAX_BUFFER_SIZE 1000

struct {
    FILE *fPtr;
    char *text;
} typedef Result;

Result scanFile(const char *fileName);

int main(int argc, char const* argv[]) {
    Result result = scanFile("text.txt");
    printf("Result:\n%s\n", result.text);
    return 0;
    if (errno != 0) {
        printf("Program ended with error: %d\n", errno);
        return -1;
    }

    printf("Result:\n%s\n", result.text);
    // Close the file
    fclose(result.fPtr);
    // Free buffer
    free(result.text);
    return 0;
}

Result scanFile(const char *fileName) {

    Result result;

    result.text = (char *)malloc(sizeof(char)*MAX_BUFFER_SIZE);

    if (result.text == NULL) {
        printf("scanFile: Faield to allocate memory!\n");
        printf("scanFile: %s\n", strerror( errno ));
        return result;
    }

    result.fPtr = fopen(fileName, "r");

    if (result.fPtr == NULL) {
        printf("scanFile: Faield to open file!\n");
        printf("scanFile: %s\n", strerror( errno ));
        return result;
    }

    unsigned int count = 0;
    int ch;

    while ((ch = fgetc(result.fPtr)) != EOF) {
        if (count < MAX_BUFFER_SIZE) {
            result.text[count] = ch;
            ++count;
        } else {
            printf("scanFile: Exceeded buffer size!\n");
            break;
        }
    }

    return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...