Хотя не все на 100% ясно, чего вы пытаетесь достичь с помощью своего кода, использование нескольких указателей немного неловко.
Первое, что должно звучать для вас как ALARM BELLS, - это ваше явное приведение к (char)
.Если вы когда-либо пытаетесь использовать преобразование, чтобы обойти предупреждения или ошибки компилятора - ОСТАНОВИТЕСЬ - вы делаете что-то не так.
Если ваша цель - предоставить до BUFFERSIZE
аргументов для execvp
(илии т.д.), тогда вам просто нужно объявить myargv
как массив указателей на символ , например
char *myargv[BUFFERSIZE] = {NULL}; /* array of pointers - init NULL */
Каждый из указателей, возвращаемых strtok
, может использоваться какмассив аргументов для execvp
, и если вы инициализируете массив для всех NULL
указателей и заполните не более BUFFERSIZE - 1
, вы всегда будете предоставлять массив аргументов для execvp
и предоставите требуемый страж * NULL
послепоследний аргумент.
Вы можете объявить свои разделители для strtok
любым удобным для вас способом, но поскольку вы правильно определяете константы с помощью #define
, нет никаких причин не добавлять константу для вашего strtok
также разделители, например,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 256
#define PROMPT "myShell >> "
#define DELIM " \n"
Если вы не используете argc
или argv
в своем коде, тогда правильное объявление для main()
:
int main (void) {
(см .: C11 Standard §5.1.2.2.1 Prзапуск программы p1 (черновик n1570) .См. Также: См. Что должно возвращать main () в C и C ++? )
Если вы только читаете строку и токенизируете строку для использования с execvp
, тогда объявление и инициализация ваших переменных в пределах цикла гарантирует, что они будут правильно инициализироваться на каждой итерации, например,
while (1) {
size_t ndx = 0, /* line index */
n = 0; /* line alloc size (0, getline decides) */
ssize_t nchr = 0; /* return (chars read by getline) */
char *line = NULL, /* buffer to read each line */
*myargv[BUFFERSIZE] = {NULL}; /* array of pointers - init NULL */
Объявляя ваши inputSize
, мои nchr
вышекак ssize_t
(правильный тип возврата для POSIX getline
), вы можете упростить свой тест для EOF
, например,
fputs (PROMPT, stdout);
if ((nchr = getline (&line, &n, stdin)) == -1) {
putchar ('\n'); /* tidy up with newline */
break;
}
Все, что остается, - это токенизация line
и назначение указателей на myargv
по правильному индексу (ndx
).Вы можете использовать цикл while
, но for
предоставляет удобный способ токенизации с strtok
, например
for (char *p = strtok (line, DELIM); p; p = strtok (NULL, DELIM)) {
myargv[ndx] = p; /* points within line, duplicate as req'd */
printf ("token: %s\n", myargv[ndx++]);
if (ndx == BUFFERSIZE - 1) /* preserve sentinel NULL */
break;
}
/* call to execvp, etc. here */
( Примечание: , просто назначив указатель натокен на myargv[ndx]
, myargv[ndx]
указывает на расположение строки в line
. Вы должны использовать указатели, пока line
остается в области. В противном случае вам нужно выделить память для каждого токена, назначить начальныйадрес для нового блока памяти - myargv[ndx]
и скопируйте токен в новый блок памяти (или malloc
и strcpy
, или strdup
, если он у вас есть))
Наконец,не забывайте, getline
выделяет, поэтому не забывайте free()
память, выделенную, когда вы закончите, например,
free (line); /* don't forget to free memory allocated by getline */
}
Если сложить все вместе, вы можете справиться с токенизацией вашей строки с чем-то похожимto:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 256
#define PROMPT "myShell >> "
#define DELIM " \n"
int main (void) {
while (1) {
size_t ndx = 0, /* line index */
n = 0; /* line alloc size (0, getline decides) */
ssize_t nchr = 0; /* return (chars read by getline) */
char *line = NULL, /* buffer to read each line */
*myargv[BUFFERSIZE] = {NULL}; /* array of pointers - init NULL */
fputs (PROMPT, stdout);
if ((nchr = getline (&line, &n, stdin)) == -1) {
putchar ('\n'); /* tidy up with newline */
break;
}
for (char *p = strtok (line, DELIM); p; p = strtok (NULL, DELIM)) {
myargv[ndx] = p; /* points within line, duplicate as req'd */
printf ("token: %s\n", myargv[ndx++]);
if (ndx == BUFFERSIZE - 1) /* preserve sentinel NULL */
break;
}
/* call to execvp, etc. here */
free (line); /* don't forget to free memory allocated by getline */
}
return 0;
}
Пример использования / Вывод
$ ./bin/getlinestrtok
myShell >> my dog has fleas
token: my
token: dog
token: has
token: fleas
myShell >> my cat has none
token: my
token: cat
token: has
token: none
myShell >> happy cat
token: happy
token: cat
myShell >>
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.