我必须编写一个像shell一样的程序。我编写了获取用户输入的函数。我还编写了将其拆分为参数的函数。 我第一次输入内容时,效果很好,但第二次在我提供的内容之后打印出不同的字符。我不必在程序中打印它。我只是这样做,看看它是否正常工作。我在网上看了很多东西,但我无法弄清楚我的错误。我想它是在makeArgs()中,但我不能精确定位它。
另外,当我给它一个输入时,readline函数在字符串的末尾添加一个\ n。我想这是因为我按下回车键。我设法通过手动替换它来解决问题,但我想知道它是否正常。
真的很感激任何帮助。 谢谢
Screenshot of Xterm after 2 inputs.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getText();
int makeArgs();
char *textEntre;
size_t nbCharacters;
char **arguments;
int main (void)
{
while (1){
getText();
int nbArguments = makeArgs();
for(int i =0; i<5; i++){
printf("%s \n",arguments[i]);
}
for(int i=0; i<nbArguments; i++){//free the char ptrs at the end
free(arguments[i]);
}
}
free(textEntre);
free(arguments);
return 0;
}
int getText(){
size_t buffersize = 0;
nbCharacters = getline(&textEntre, &buffersize, stdin);
textEntre[nbCharacters-1] =' '; // when I press enter it regiter the enter as \n so I replace it with a space
return 0;
}
int makeArgs(){
arguments = (char **)malloc(sizeof(char*)*20);
int i;
int j = 0;
int k = 0;
int nbElem = 20; //the number of ptrs that can be in arguments
for(i = 0; i<nbCharacters; i++){
if(i == 20){ //increases the memory allocated if there are more than 20 arguments
nbElem = nbElem *2;
arguments = (char **)realloc(arguments, sizeof(char*)*nbElem);
}
if(textEntre[i] == '"'){ //checks for ""
i++;
while(textEntre[i] != '"'){
i++;
}
}
if(textEntre[i] == ' ' && textEntre[i-1] == ' '){ // eliminates useless spaces
j++;
}
else if(textEntre[i] == ' '){ //save a single argument
char * chptr;
chptr = (char *)malloc(i-j+1); //giving +1 for the \0 at the end
strncpy(chptr, &textEntre[j], i-j);
arguments[k] = chptr;
k++;
j = i +1;
}
}
return k;
}
答案 0 :(得分:1)
chptr = (char *)malloc(i-j+1); //giving +1 for the \0 at the end
您为终止\0
正确分配了内存,但实际上在哪里添加&#34; \ 0到最后&#34;?
strncpy(chptr, &textEntre[j], i-j);
strncpy
不一定是零终止目标缓冲区。你必须自己做。
事实上,在这个特定的应用程序中strncpy
是一个相当不合适的函数:它不会给你任何超过普通memcpy
的东西,并且可能效率较低。你可以做到
memcpy(chptr, &textEntre[j], i - j);
具有更高的效率。而且,再次,不要忘记将目标缓冲区置零。
或者您可以将sprintf
用于以下相同的目的
sprintf(chptr, "%.*s", i - j, &textEntre[j]);
将在目标中生成一个正确的以零结尾的字符串。 (虽然你不会经常看到sprintf
以这种方式使用过。)