字符串操作 - 奇怪的字符

时间:2014-03-20 13:26:30

标签: c unix

说明

我用fgets()读取userinput(例如" ls -l /")并调用Parse(),它被分开(" ls"" -l&# 34;" \")供以后使用。

问题是:来自第一个周期的令牌中有令人毛骨悚然的字符(下面的屏幕截图),但从那里输出就很好了。 我试图用零来初始化两个缓冲区而不改变行为。请解释我的第一个输出中发生的事情。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>

typedef char* string;
char inputBuffer[512];
string parse[256];
int j,parseCount;
void Parse(void);


void Parse(void)
{
    char buffer[512];
    string token;
    token = " ";
    strcpy(buffer, inputBuffer);
    j=0;
    parse[j] = strtok (buffer, token); 
    while (parse[j] != NULL)
    {
        j++;
        parse[j] = strtok (NULL, token); 
    }
    parseCount =j;  
}

int main (void)
{
    printf(">> ");
    fgets(inputBuffer, 512, stdin);   /* input buffer, max.Input(char), whereFrom?*/
    Parse();
    for (j=0;j<parseCount;j++){
         printf("[%d] %s\n",j, parse[j]);
    }
    return main(); 
}

output

1 个答案:

答案 0 :(得分:4)

这一行

parse[j] = strtok (buffer, token); 

将内存地址存储在buffer中,Parse()是本地的。{1}}。返回buffer时,代表Parse()的内存无效,因此当尝试取消引用以打印它们所引用的内容时,parse中存储的地址也将无效。

要解决此问题,请调用函数创建一个临时工作缓冲区并向下传递给`Parse()对它的引用:

char * parse[256] = 0;
char buffer[512] = "";
size_t parseCount = 0;

void Parse(char * buffer)
{
  const char * token = " ";
  size_t j = 0;
  parse[j] = strtok(buffer, token);
  while (parse[j] != NULL)
  {
    j++;
    parse[j] = strtok(NULL, token);
  }
  parseCount = j;
}

int main(void)
{
  fgets(buffer, 512, stdin);
  {
    char buffer_tmp[512];
    strcpy(buffer_tmp, buffer);
    Parse(buffer_tmp);

    for (size_t j = 0; j < parseCount; j++)
    {
      printf("[%zu] %s\n", j, parse[j]);
    }
  }
  return 0;
}

由于我不喜欢全局变量,我更喜欢以下内容:

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

size_t parse(char * buffer, char ** parse)
{
  const char * token = " ";
  size_t j = 0;
  parse[j] = strtok(buffer, token);
  while (parse[j] != NULL)
  {
    j++;
    parse[j] = strtok(NULL, token);
  }
  return j;
}

#define IN_MAX (512 + 1 + 1)

int main(void)
{
  char buffer[IN_MAX] = "";

  if (NULL != fgets(buffer, IN_MAX, stdin))
  {
    char buffer_tmp[IN_MAX];
    strcpy(buffer_tmp, buffer);

    {
      size_t parse_count = 0;
      char * parse[IN_MAX/2 + 1] = 0; 
      size_t parse_count = parse(buffer_tmp, parse);

      for (size_t j = 0; j < parse_count; j++)
      {
        printf("[%zu] %s\n", j, parse[j]);
      }
    }
  }
  else if (ferror())
  {
    fprintf(stderr, "Error reading from inout stream.\n");
  }

  return 0;
}