ошибка сегментации в нижнем / верхнем преобразовании - PullRequest
0 голосов
/ 01 мая 2020

Вот весь мой исходный код:

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

int main(int argc, char *argv[])
{
    printf("usage: %s l(ower)/u(pper)", argv[0]);

    int (*convert)(int c) = NULL;
    int c;

    if (argc != 2)
      printf("usage: %s l(ower)/u(pper)", argv[0]);

    if (strcmp(argv[1], "l") == 0 || strcmp(argv[1], "lower") == 0)
      convert = tolower;
    else if(strcmp(argv[1], "u") == 0 || strcmp(argv[1], "upper") == 0)
      convert = toupper;
    else
      printf("usage: %s l(ower)/u(pper)", argv[0]);

    while ((c = getchar()) != EOF)
      putchar((*convert)(c));

    return 0;
}

Я компилирую этот код с помощью cc и запускаю его на MacBook. Ошибка сегментации получена.

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Если вы запускаете код без аргументов или с неверными аргументами, операторы printf сообщают вам об этом, но затем программа продолжает работать, так что вы, вероятно, вызываете указатель функции 'convert', пока он все еще установлен в NULL. Это вызовет sh, прежде чем вы увидите сообщения о том, что вы не даете программе правильные аргументы. Возможно, вы захотите поставить 'return 1' или что-то еще после того, как операторы print сообщат вам, что аргументы отсутствуют или неверны. Если вы это сделаете, вам нужно будет заключить в скобки все предложение «if» или «else», иначе операторы return будут безусловно выполняться. Ваш стиль отступов немного нестандартен. Возможно, именно поэтому вы упустили из виду тот факт, что после команды printf, сообщающей вам, что программа работает неправильно, нет операторов return.

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

int main(int argc, char *argv[])
{
    printf("uasge: %s l(ower)/u(pper)", argv[0]);

    int (*convert)(int c) = NULL;
    int c;

    if (argc != 2) {
        printf("uasge: %s l(ower)/u(pper)", argv[0]);
        return 1;
    }

    if (strcmp(argv[1], "l") == 0 || strcmp(argv[1], "lower") == 0) {
        convert = tolower;
    } else if(strcmp(argv[1], "u") == 0 || strcmp(argv[1], "upper") == 0) {
        convert = toupper;
    } else {
        printf("uasge: %s l(ower)/u(pper)", argv[0]);
        return 1;
    }
    while ((c = getchar()) != EOF)
        putchar((*convert)(c));

    return 0;
}
0 голосов
/ 01 мая 2020

В вашем коде есть несколько проблем по порядку:

Почему вы печатаете использование, даже если аргумент действителен? первый printf должен быть удален

В

if (argc != 2)
printf("usage: %s l(ower)/u(pper)", argv[0]);

вы определяете, является ли номер аргумента неправильным, но в этом случае вы печатаете использование и продолжаете например, если этот номер правильный, поэтому, если вы вызываете вашу программу без аргументов, вы будете вызывать strcmp с NULL в качестве первого аргумента с неопределенным поведением

In

else
printf("usage: %s l(ower)/u(pper)", argv[0]);

если аргумент не l / lower / u или upper, вы вводите в этом else case, но в нем вы печатаете использование и снова продолжаете, как будто ошибки нет, поэтому в этом случае convert не инициализирован, поведение будет неопределенным, когда вы будете использовать его для вызова функции преобразования.


Один из способов сделать это:

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

int main(int argc, char *argv[])
{
    int (*convert)(int c) = NULL;

    if (argc == 2) {
      if (strcmp(argv[1], "l") == 0 || strcmp(argv[1], "lower") == 0)
        convert = tolower;
      else if(strcmp(argv[1], "u") == 0 || strcmp(argv[1], "upper") == 0)
        convert = toupper;
    }

    if (convert == NULL)
      printf("usage: %s l(ower)/u(pper)\n", argv[0]);
    else {
      int c;

      while ((c = getchar()) != EOF)
        putchar(convert(c));
    }

    return 0;
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc -g -Wall cv.c
pi@raspberrypi:/tmp $ ./a.out
uasge: ./a.out l(ower)/u(pper)
pi@raspberrypi:/tmp $ ./a.out a z
uasge: ./a.out l(ower)/u(pper)
pi@raspberrypi:/tmp $ ./a.out z
uasge: ./a.out l(ower)/u(pper)
pi@raspberrypi:/tmp $ ./a.out u
a
A
P
P
(
(
...