我想在C中编写一个程序,在一个单独的行中显示整个句子的每个单词(作为输入)。这就是我到目前为止所做的:
void manipulate(char *buffer);
int get_words(char *buffer);
int main(){
char buff[100];
printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff)); // Debugging reasons
bzero(buff, sizeof(buff));
printf("Give me the text:\n");
fgets(buff, sizeof(buff), stdin);
manipulate(buff);
return 0;
}
int get_words(char *buffer){ // Function that gets the word count, by counting the spaces.
int count;
int wordcount = 0;
char ch;
for (count = 0; count < strlen(buffer); count ++){
ch = buffer[count];
if((isblank(ch)) || (buffer[count] == '\0')){ // if the character is blank, or null byte add 1 to the wordcounter
wordcount += 1;
}
}
printf("%d\n\n", wordcount);
return wordcount;
}
void manipulate(char *buffer){
int words = get_words(buffer);
char *newbuff[words];
char *ptr;
int count = 0;
int count2 = 0;
char ch = '\n';
ptr = buffer;
bzero(newbuff, sizeof(newbuff));
for (count = 0; count < 100; count ++){
ch = buffer[count];
if (isblank(ch) || buffer[count] == '\0'){
buffer[count] = '\0';
if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
printf("MALLOC ERROR!\n");
exit(-1);
}
strcpy(newbuff[count2], ptr);
printf("\n%s\n",newbuff[count2]);
ptr = &buffer[count + 1];
count2 ++;
}
}
}
虽然输出是我想要的,但是在显示最后一个单词之后我真的有很多黑色空格,而malloc()返回NULL所以MALLOC错误!显示在最后。 我可以理解我的malloc()实现有一个错误,但我不知道它是什么。
还有另一种更优雅 - 通常更好的方法吗?
提前致谢。
答案 0 :(得分:79)
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
看看这个,并使用空格字符作为分隔符。如果您需要更多提示,请告诉我。
来自网站:
char * strtok ( char * str, const char * delimiters );
在第一次调用时,函数需要一个C字符串作为str的参数,其第一个字符用作扫描标记的起始位置。在后续调用中,函数需要一个空指针,并在最后一个令牌结束后立即使用该位置作为扫描的新起始位置。
在strtok调用中找到str的终止空字符后,对该函数的所有后续调用(使用空指针作为第一个参数)将返回空指针。
参数
- STR
- C string to truncate。
- 请注意,此字符串通过分解为较小的字符串(标记)进行修改。 替代[sic],可以指定空指针,在这种情况下,函数继续扫描先前成功调用函数的位置。
- 定界符
- 包含分隔符字符的C字符串。
- 这些可能因电话而异。
返回值
指向字符串中找到的最后一个标记的指针。 如果没有要检索的标记,则返回空指针。
实施例
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
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, " ,.-");
}
return 0;
}
答案 1 :(得分:4)
为了好玩,这里有一个基于回调方法的实现:
const char* find(const char* s,
const char* e,
int (*pred)(char))
{
while( s != e && !pred(*s) ) ++s;
return s;
}
void split_on_ws(const char* s,
const char* e,
void (*callback)(const char*, const char*))
{
const char* p = s;
while( s != e ) {
s = find(s, e, isspace);
callback(p, s);
p = s = find(s, e, isnotspace);
}
}
void handle_word(const char* s, const char* e)
{
// handle the word that starts at s and ends at e
}
int main()
{
split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
答案 2 :(得分:1)
malloc(0)
可以(可选)返回NULL
,具体取决于实施方式。你知道为什么你可能会打电话给malloc(0)
吗?或者更确切地说,你是否看到你的阅读和写作超出阵列的大小?
答案 3 :(得分:1)
正如其他人所建议的那样,考虑使用strtok_r
,或类似:
void printWords(const char *string) {
// Make a local copy of the string that we can manipulate.
char * const copy = strdup(string);
char *space = copy;
// Find the next space in the string, and replace it with a newline.
while (space = strchr(space,' ')) *space = '\n';
// There are no more spaces in the string; print out our modified copy.
printf("%s\n", copy);
// Free our local copy
free(copy);
}
答案 4 :(得分:0)
出现问题的是get_words()
总是返回少于实际字数的一个,所以最终你会尝试:
char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */
newbuff[count2] = (char *)malloc(strlen(buffer))
最终, count2
总是比您为newbuff[]
声明的元素数量多一个。为什么malloc()
没有返回有效的ptr,但我不知道。
答案 5 :(得分:0)
你应该是malloc'ing strlen(ptr),而不是strlen(buf)。此外,您的count2应限制为单词数量。当你到达字符串的末尾时,你继续遍历缓冲区中的零并为数组添加零大小的字符串。
答案 6 :(得分:0)
就像C中不同风格的字符串操作一样,这里有一个不修改源字符串的示例,并且不使用malloc
。要查找空格,我使用libc函数strpbrk
。
int print_words(const char *string, FILE *f)
{
static const char space_characters[] = " \t";
const char *next_space;
// Find the next space in the string
//
while ((next_space = strpbrk(string, space_characters)))
{
const char *p;
// If there are non-space characters between what we found
// and what we started from, print them.
//
if (next_space != string)
{
for (p=string; p<next_space; p++)
{
if(fputc(*p, f) == EOF)
{
return -1;
}
}
// Print a newline
//
if (fputc('\n', f) == EOF)
{
return -1;
}
}
// Advance next_space until we hit a non-space character
//
while (*next_space && strchr(space_characters, *next_space))
{
next_space++;
}
// Advance the string
//
string = next_space;
}
// Handle the case where there are no spaces left in the string
//
if (*string)
{
if (fprintf(f, "%s\n", string) < 0)
{
return -1;
}
}
return 0;
}
答案 7 :(得分:0)
如果发现它只是打印换行,则可以扫描字符数组以查找令牌,否则打印 cha r。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
int len = strlen(s);
char delim =' ';
for(int i = 0; i < len; i++) {
if(s[i] == delim) {
printf("\n");
}
else {
printf("%c", s[i]);
}
}
free(s);
return 0;
}
答案 8 :(得分:-1)
char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);
for(i=0;i<l;i++){
if(arr[i]==32){
printf("\n");
}
else
printf("%c",arr[i]);
}