0

例如,如果一个指针指向一个字符数组,上面写着“你好,你好吗?” 而您只希望指针指向 Hello。我传入一个 char 指针,当我计算它时,它会读取整个数组。我尝试使用一个 for 循环来减小大小,该循环在遇到“”时会中断。但我没有运气弄清楚。有任何想法吗?

const char *infile(char * file )
{
    cout<<file<<endl;  //this prints out the entire array
    int j;
    for(j=0;j<500; j++)
    {
        if(file[j]==' ')
           break;
    }
    strncpy(file, file,  j);
    cout<<file<<endl;  //how to get this to print out only the first word
}
4

11 回答 11

2

strncpy()j如果源字符串的第一个字节中没有空终止符,则不会附加空终止符。而你的情况,没有。

我认为您想要做的是将第一个空格手动更改为\0

for (j = 0; j < 500; j++) {
  if (file[j] == ' ') {
    file[j] = '\0';
    break;
  }
}
于 2012-04-16T19:37:19.057 回答
2

首先,避免使用 strtok(就像它最常见的瘟疫一样)。这是令人不快的,但有时在 C 中是合理的。不过,我还没有看到我所说的在 C++ 中使用它的理由。

其次,可能最简单的处理方法(假设您使用的是 C++)是使用字符串流:

void infile(char const *file) 
{
    std::strinstream buffer(file);
    std::string word;
    buffer >> word;
    std::cout << word;
}

另一种可能性是使用 std::string 中内置的一些函数:

void infile(char const *file) {
    std::string f(file);
    std::cout << std::string(f, 0, f.find(" "));
}

...现在我想起来,这可能比stringstream事物的版本简单一些。

于 2012-04-16T19:39:13.607 回答
1

char*指针实际上只指向一个对象char。如果该对象恰好是字符串的第一个(或任何)元素,您可以使用指针算法来访问该字符串的其他元素——这就是字符串(C 风格的字符串,而不是 C++ 风格std::string的对象)通常的样子访问。

(C 风格)字符串只是一个以空字符 (' \0') 结尾的字符序列。('\0'终止符之后的任何内容都不是字符串的一部分。)因此,字符串"foo bar"由以下字符序列组成:

{ 'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0' }

如果要将字符串从更改"foo bar"为 just "foo",一种方法是将空格字符替换为空字符:

{ 'f', 'o', 'o', '\0', ... }

...不是语法的一部分;它表示仍然存在的字符('b', 'a', 'r', '\0'),但不再是字符串的一部分。

由于您使用的是 C++,因此使用std::string;可能会更好。它更加强大和灵活,让您不必担心终结符、内存分配和其他细节。(当然,除非这个练习的目的是学习 C 风格的字符串是如何工作的。)

请注意,这会修改指向的字符串file,并且该更改将对调用者可见。您可以通过制作字符串的本地副本来避免这种情况(这需要为其分配空间,然后释放该空间)。再次,std::string使这种事情变得容易得多。

最后,这个:

strncpy(file, file,  j);

在几个层面上都不好。像这样使用重叠的源和目标调用strncpy()具有未定义的行为;从字面上看,任何事情都可能发生。并且strncpy()不一定在目的地提供适当的 NUL 终止符。从某种意义上说,strncpy()它并不是一个真正的字符串函数。你最好假装它不存在。

见我对这个话题的咆哮

于 2012-04-16T19:49:03.893 回答
0
std::copy(file, std::find(file, file+500, ' '),
          std::ostream_iterator<char>(std::cout, ""));
于 2012-04-16T22:17:02.693 回答
0

这与指针的大小无关。对于特定类型,指针始终具有相同的大小。

strtok 可能是最好的解决方案(使用 strtok 的这段代码每次遇到空格、“、”、点或“-”时都会将字符串分解为子字符串。

char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }

资料来源:CPP STTOK

于 2012-04-16T19:33:58.973 回答
0

这样做会容易得多

 if(file[j]==' ') {
   file[j] = 0;
   break;
   ..

  // strncpy(file, file,  j);
于 2012-04-16T19:35:06.387 回答
0

使用strtok可能会让您的生活更轻松。
使用 ' ' 作为分隔符拆分字符串,然后打印您从中获得的第一个元素strtok

于 2012-04-16T19:35:19.193 回答
0

使用“strtok”,参见例如http://www.cplusplus.com/reference/clibrary/cstring/strtok/

于 2012-04-16T19:35:33.187 回答
0

如果您要问的是“我可以动态调整此指针指向的内存块的大小”那么......不是真的,不。(您必须创建一个所需大小的新块,然后复制字节,删除第一个块等)

如果您只想“打印第一个单词”,则将空格位置的字符设置为 0。然后,当您输出 file* 指针时,您只会得到第一个单词(直到 \0 .) (阅读以空字符结尾的字符串,了解更多关于为什么会这样工作的信息。)

但这一切都取决于你所做的有多少是一个例子来展示你试图解决的问题。如果您真的“拆分字符串”,那么您至少要考虑使用strtok

于 2012-04-16T19:39:18.837 回答
0

为什么不一次输出每个字符,然后在遇到空格时中断。

const char *infile(char * file )
{
  cout<<file<<endl;  //this prints out the entire array
  int j;

  for(j=0;j<500; j++)
  {
    if(file[j]==' ')
       break;
    cout<<file[j];
  }

  cout<<endl;
}
于 2012-04-16T19:39:23.540 回答
0

如果您使用 malloc 分配了 char * 指向的空间,则可以使用 realloc 更改大小。

char * pzFile = malloc(sizeof("Hello how are you?" + 1));
strcpy(pzFile, "Hello how are you?");
realloc(pzFile, 6);
pzFile[6] = '\0';

请注意,如果不设置空指针,使用字符串可能会导致问题。

如果您只是想缩短字符串,您所要做的就是在位置 6 处设置空终止符。分配的空间比需要的空间大,但只要不短就可以了。

我强烈建议您最想做的是将字符串复制到空格中。

char * pzInput = malloc(sizeof("Hello how are you?" + 1));
strcpy(pzInput, "Hello how are you?");
char * pzBuffer = malloc(BUFFER_SIZE);

char * pzSrc = pzInput;
char * pzDst = pzBuffer;
while (*pzSrc && ' ' != *pzSrc)
  *(pzDst++) = *(pzSrc++);
*pzDst = '\0';

这也会导致 pzSrc 指向字符串的其余部分以供以后使用!

于 2012-04-16T19:56:36.943 回答