C: Как сделать аргумент NULL "функции возврата указателя" безопасным?

Итак, я кодирую функцию верхнего регистра с использованием указателей. Я пытаюсь сделать сообщение об ОШИБКЕ, когда есть ввод, но, к сожалению, в терминале я не вижу ничего похожего на то, что s==NULL работает не очень хорошо, я не вижу никаких сообщений об ОШИБКЕ.

Вероятно, проблема с типами аргументов и указателем, но я этого не вижу!

Если мои аргументы программы выглядят так:

"Hello 123dsd" "teSting"

Выход:

HELLO 123DSD

TESTING

Если аргументы моей программы пусты:

вывод ничего:

Я хочу показать сообщение об ОШИБКЕ, если аргументы пусты, например:

Please insert a string!

Вот мой код:

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

#define MAGIC_NUMBER 32

char *uppercase(char *s)
{
    if (s == NULL)
    {
        printf("Please insert a string!");
        return 0; //Not working!!
    }
    else
    {
        for(char *p = s; *p!=0; ++p)
        {
            if ('a' <= *p && *p <= 'z')
                *p = *p - MAGIC_NUMBER;
        }

        return s;
    }
}


int main(int argc, char *argv[])
{
    for(int i=1; i < argc; i++)
    {
        printf("%s \n", uppercase(argv[i]));
    }


    return 0;
}

С *s == NULL вы разыменовываете s, поэтому он возвращает значение первого символа массива. Итак, вы хотите проверить значение указателя и хотите s == NULL (без *)

Craig Estey 11.12.2020 23:29

Что именно означает «не очень хорошо работает» или «Не работает!». argv[i] с i<argc никогда не должно быть указателем NULL. Хотя некоторые реализации printf будут печатать (null) при передаче указателя NULL, это поведение undefined. Вы должны проверять возвращаемое значение функции, которая может возвращать NULL, и передавать его в printf, только если это не NULL.

Bodo 11.12.2020 23:30

@Bodo Можете ли вы показать с кодом, я был бы так счастлив, большое спасибо за ваше время!

Barak 11.12.2020 23:33

Вместо MAGIC_NUMBER вы можете сделать его немного менее волшебным, написав 'a' - 'A'

William Pursell 11.12.2020 23:36

@WilliamPursell Я не могу #define, как будто этот результат портит его, давая мне @ вместо заглавных букв

Barak 11.12.2020 23:39

@Bobamas Во-первых, примените предложение в комментарии Крейга Эсти. Затем, пожалуйста, отредактируйте свой вопрос и покажите командную строку, которую вы используете для запуска своей программы, фактический и ожидаемый результат. Или опишите, чего вы хотите добиться. Без этого непонятно, как модифицировать код под свои нужды. Что именно вы хотите, чтобы я показал? Как избежать передачи указателя NULL на printf?

Bodo 11.12.2020 23:39

@Bobamas #define MAGIC_NUMBER ('a' - 'A') должно работать без проблем. В вашем случае это должно работать даже без круглых скобок, но я рекомендую оставить круглые скобки.

Bodo 11.12.2020 23:42

@Bodo Большое спасибо, я редактирую свой вопрос, надеюсь, он намного понятнее?

Barak 11.12.2020 23:46

@Bobamas Я намеренно добавил имя программы myprogram в командную строку, чтобы читателю было более понятно, что это командная строка, а не какой-либо другой тип ввода. Конечно, я не предполагаю, что ваша программа на самом деле называется myprogram, но это имя не имеет большого значения для примера в вопросе.

Bodo 12.12.2020 00:10

Большое спасибо @Bodo

Barak 12.12.2020 00:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
10
174
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если вы не вводите никаких параметров в программу, argc будет равно 1, поэтому цикл for в функции main никогда не будет введен. Это также означает, что указатель NULL никогда не будет передан в uppercase.

Вам нужно переместить проверку отсутствующих аргументов на main:

int main(int argc, char *argv[])
{
    if (argc == 1) {
        printf("Please insert a string!");
        return 1;
    }
    for(int i=1; i < argc; i++)
    {
        printf("%s \n", uppercase(argv[i]));
    }

    return 0;
}

Большое спасибо! Я боролся с этими аргументами более часа!

Barak 11.12.2020 23:55
Ответ принят как подходящий

Если вы вызовете свою программу без аргументов, она ничего не напечатает, потому что цикл не вызовет printf или uppercase, поскольку argc будет иметь значение 1.

Вы должны добавить код в main, чтобы обработать этот случай.

int main(int argc, char *argv[])
{

    if (argc < 2)
    {
        fprintf(stderr, "Please insert a string!\n")
        return 1;
    }

    for(int i=1; i < argc; i++)
    {
        printf("%s \n", uppercase(argv[i]));
    }


    return 0;
}

Обратите внимание, что я использую fprintf(stderr, ...) для сообщения об ошибке, потому что сообщения об ошибках не должны смешиваться с обычным выводом.

Другие вопросы по теме