Печать аргументов командной строки char by char в C - PullRequest
1 голос
/ 12 октября 2011

Вот что у меня есть:

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

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

    while(*argv++ != 0)
    {
            printf("Argument!\n");
            printf("%s %d\n",*argv,(int)strlen(*argv));
            int i = 0;

            while(*argv[i])
            {
                    printf("char!\n");
                    printf("%c\n",*argv[i]);
                    i++;
            }

            printf("End of for loop\n");
    }

    return 0;
}

Когда я запускаю тест ./a.out, вывод:

Argument!
test 4
char!
t
Segmentation Fault

Я смотрел на это несколько часов. Почему моя программа не печатает каждый аргумент командной строки символ за символом?

Я новичок в C, и двойственность указателя массива, поэтому я не удивлюсь, если бы это была проблема. Любая помощь приветствуется!

Ответы [ 5 ]

4 голосов
/ 12 октября 2011

Первая версия

То, что вы хотите, это использовать argc:

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

int main(int argc, char **argv)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < argc; i ++)
    {
    j = 0;      
    while(argv[i][j] != '\0')
       printf("Argument %d letter %d : %c\n", i,j,argv[i][j++]);   
    }
    return 0;
}

Вывод на самом деле буквенно-буквенный, как вам нужно:

$./a.out hello world
Argument 0 letter 1 : .
Argument 0 letter 2 : /
Argument 0 letter 3 : a
Argument 0 letter 4 : .
Argument 0 letter 5 : o
Argument 0 letter 6 : u
Argument 0 letter 7 : t
Argument 1 letter 1 : h
Argument 1 letter 2 : e
Argument 1 letter 3 : l
Argument 1 letter 4 : l
Argument 1 letter 5 : o
Argument 2 letter 1 : w
Argument 2 letter 2 : o
Argument 2 letter 3 : r
Argument 2 letter 4 : l
Argument 2 letter 5 : d

Вторая версия:

Вы можете использовать обозначение указателя для j, но не для i, так как вы не знаете количество букв каждого аргумента.Конечно, это может быть достигнуто с помощью strlen, что приведет к итерации по строке для подсчета буквы, а это не то, что вы хотите сделать.Если вы можете сделать это за одну итерацию аргумента, зачем делать это за две?

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

int main(int argc, char **argv)
{
    int i = 0;int j = 0;
    while(i < argc)
    {
    j=0;
    while(*(argv[i]+j) != '\0')
    {
            printf("Argument %d letter %d : %c\n", i,j,*(argv[i]+(j)));
            j++;
    } 
     i++;
    }
    return 0;

}
4 голосов
/ 12 октября 2011

Попробуйте это:

while(argv) {
    printf("%s\n", *argv); /* %s instead of %c and drop [i]. */
    argv++; /* Next arg. */
}

Когда вы говорите *argv[i], , если argv[i] НЕДЕЙСТВИТЕЛЕН, он потерпит неудачу по очевидным причинам .

Ты не должен следовать за указателем NULL, потому что хаос и безумие ждут тебя в конце.

2 голосов
/ 12 октября 2011
2 голосов
/ 12 октября 2011

У вас две проблемы. Во-первых, вы увеличиваете argv, чтобы указывать на следующую строку в начале каждой итерации внешнего цикла while. Когда это дойдет до последнего аргумента, argv будет NULL вводом последней итерации, что приведет к ошибке по умолчанию, когда вы разыменовываете ее.

Во-вторых, во внутреннем цикле смешан порядок операций. *argv[i] индексирует в argv и затем разыменовывает его, который принимает первый символ i -ой строки, начиная с текущего индекса. Если i превышает количество оставшихся аргументов, это также приведет к segfault.

Перепишите внешний цикл как while(*(++argv)) (круглые скобки вокруг ++argv необязательны, но полезны), так что argv увеличивается до проверки нуля; если вы также хотите распечатать имя программы (в argv[0]), то переместите инкремент в конец цикла, а не в условие цикла.

Перепишите свой внутренний цикл как while((*argv)[i]), и перепишите внутренний оператор printf, чтобы он также использовал (*argv)[i], чтобы текущий аргумент разыменовывался и затем индексировался в этом порядке.

1 голос
/ 12 октября 2011
  1. Изменение argv напрямую не звучит как отличная идея.Сделайте копию и используйте ее по своему усмотрению.

  2. Вы не можете предположить, что argv будет в какой-то момент указывать на 0.

  3. Такие вещи, как *argv[i] чрезвычайно трудно читать: это (*argv)[i], или *(argv[i]) ...

Будьте очень осторожны при использовании указателей, в противном случае вы продолжите получать segfault.

Кажется, работает следующий код:

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

int main(int argc, char **argv)
{
    char **currentArgv = argv;
    int currentArgc = 0;
    while(++currentArgc < argc)
    {
            printf("Argument!\n");
            printf("%s %d\n",currentArgv[currentArgc],(int)strlen(currentArgv[currentArgc]));
            int i = 0;

            while(currentArgv[currentArgc][i]!='\0')
            {
                    printf("char!\n");
                    printf("%c\n",currentArgv[currentArgc][i]);
                        i++;
            }

            printf("End of for loop\n");
    }

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