我有一个非常愚蠢的问题,我无法逾越。
目标是接受用户给定的字符串,然后将其按空格分割,然后将其放入数组中。
这是我目前的当前代码
#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;
}
}
}
当我尝试编译它时,我得到警告,
警告:从指针转换为不同大小的整数 [-指向指针的指针] myargv [i] =(字符)令牌;
不确定我到底在做什么错。
谢谢!
答案 0 :(得分:2)
虽然并不能100%清楚您要用代码完成的全部工作,但是使用多个指针有点尴尬。
对您来说,响起警钟的第一件事是您需要明确地转换为(char)
。如果您发现自己试图进行转换以避开编译器警告或错误-停止-您做错了什么。
如果您的目标是为BUFFERSIZE
(或诸如此类)提供多达execvp
个参数,那么您只需要声明myargv
作为指向char的指针数组,例如
char *myargv[BUFFERSIZE] = {NULL}; /* array of pointers - init NULL */
strtok
返回的每个指针都可以用作execvp
的参数数组,并且如果您将数组初始化为所有NULL
指针并且填充量不超过{{1} },请确保始终为BUFFERSIZE - 1
提供一个参数数组,并在最后一个参数之后提供所需的哨兵execvp
。
您可以随意声明NULL
的分隔符,但是由于您使用strtok
正确定义了常量,因此没有理由不为#define
分隔符添加常量还有,例如</ p>
strtok
如果您未在代码中使用#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 256
#define PROMPT "myShell >> "
#define DELIM " \n"
或argc
,则argv
的正确声明为:
main()
(请参阅:C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570)。另请参见:See What should main() return in C and C++?)
如果仅读取行并标记要与int main (void) {
一起使用的行,则在循环范围内声明并初始化变量 确保它们是正确地重新初始化每次迭代,例如
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
(POSIX ssize_t
的正确返回类型),可以简化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 */
}
使用/输出示例
#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;
}
仔细检查一下,如果还有其他问题,请告诉我。
答案 1 :(得分:0)
来自strtok
char * strtok(char * str,const char * delim);
在您的作业中,返回类型为char *
myargv[i] = (char) tokens;
您正在做typecast
到char *
的{{1}},我确定这不是您想做的事
可能与此有关
更改char
以容纳令牌数组
myargv
,并在char myargv[MAX_TOKENS][BUFFERSIZE];
循环而不是分配while
中使用myargv[i] = (char) tokens
strcpy
让我尝试解释为什么您的原始程序行为异常
strcpy(myargv[i], tokens);
printf("%s\n", myargv[i]);
在这里char myargv[BUFFERSIZE];
被分配了一个myargv
vitz 256的内存,如
BUFFERSIZE
每个块的大小为+---+---+---+---+---+---+---+---+....---+---+
| | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
0 1 2 .. 255
或sizeof(char)
在1 byte
循环此处
while
您有一个myargv[i] = (char) tokens;
,本质上是一个char *
数字,如果您真的去那个地址并查看那里的内容4 byte
,则应该已经看到第一个令牌。但是,您现在正尝试将byte by byte
放入4 byte address
中,导致截断和赋值。
然后是1 byte indexed location
printf
根据上一步的操作,printf("%c\n", myargv[i]);
现在包含一个地址的剥离版本,该地址只是一个数字myargv[i]
格式说明符尝试将其转换为相应的{{1 }},并打印出垃圾内容。
我建议您阅读"%c\n"
,ascii
,2d-arrays