我有一个非常愚蠢的问题,我无法通过。
目标是接收用户给定的字符串,将其按空格拆分,然后将其放入数组中。
这是我目前的代码
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFERSIZE 256
#define PROMPT "myShell >> "
#define PROMPTSIZE sizeof(PROMPT)
int main(int argc, char **argv) {
//execvp() to locate executable
char *buffer;
size_t bufferSize = BUFFERSIZE;
size_t inputSize;
char *tokens;
char myargv[BUFFERSIZE];
buffer = (char *) malloc(bufferSize * sizeof(char));
tokens = (char *) malloc(bufferSize * sizeof(char));
while (1) {
printf(PROMPT);
inputSize = (size_t) getline(&buffer, &bufferSize, stdin);
if (inputSize == 18446744073709551615) {
break;
}
int i = 0;
tokens = strtok(buffer, " ");
while (tokens != NULL) {
myargv[i] = (char) tokens;
printf("%c\n", myargv[i]);
tokens = strtok(NULL, " ");
i = i + 1;
}
}
}
当我尝试编译它时,我收到了警告,
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] myargv[i] = (char) tokens;
不太确定我做错了什么。
谢谢!
最佳答案
虽然不是 100% 清楚您要用您的代码完成的所有内容,但您对多个指针的使用有点笨拙。
应该为您敲响警钟的第一件事是您需要显式转换为 (char)
。如果您发现自己试图强制转换以绕过编译器警告或错误——停止——你做错了什么。
如果您的目标是向 execvp
(或类似的)提供最多 BUFFERSIZE
个参数,那么您只需将 myargv
声明为指向 char 的指针数组,例如
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 Program startup p1 (draft n1570)。另请参见:See What should main() return in C and 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
声明为 ssize_t
(POSIX getline
的正确返回类型) ,您可以简化对 EOF
的测试,例如
fputs (PROMPT, stdout);
if ((nchr = getline (&line, &n, stdin)) == -1) {
putchar ('\n'); /* tidy up with newline */
break;
}
剩下的就是标记 line
并将指针分配给位于适当索引 (ndx
) 的 myargv
。您可以使用 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
保留在范围内时使用指针。否则,您需要为每个标记分配内存,为新 block 分配起始地址内存到 myargv[ndx]
并将 token 复制到新的内存块。(malloc
和 strcpy
,或 strdup
如果你有的话))
最后,不要忘记,getline
分配,所以不要忘记 free()
分配的内存,例如,
free (line); /* don't forget to free memory allocated by getline */
}
总而言之,您可以使用类似以下内容来标记您的行:
#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 >>
检查一下,如果您还有其他问题,请告诉我。
关于c - 通过分隔符将 getline 解析为缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52866872/