我编写了一个程序,用于计算用户输入的字符串中字母和单词的出现次数。我已经成功地完成了大部分工作,但是,我还必须将我存储在指针数组中的单词按字母顺序排列。我看到一个函数void sortstring()应该只是这个但它似乎根本不起作用。我该怎么做呢?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void findLetters(char *ptr);
void findWords(char *point);
void sort_string(char *p);
int main()
{
char textStream[100]; //up to 98 characters and '\n\ and '\0'
printf("enter some text\n");
if (fgets(textStream, sizeof (textStream), stdin)) //input up to 99 characters
{
findLetters(textStream);
findWords(textStream);
sort_string(textStream);
}
else
{
printf("fgets failed\n");
}
return 0;
}
void findLetters(char *ptr) //find occurences of all letters
{
int upLetters[26];
int loLetters[26];
int i;
int index;
for (i = 0; i < 26; i++) // set array to all zero
{
upLetters[i] = 0;
loLetters[i] = 0;
}
i = 0;
while (ptr[i] != '\0') // loop until prt[i] is '\0'
{
if (ptr[i] >= 'A' && ptr[i] <= 'Z') //stores occurrences of uppercase letters
{
index = ptr[i] - 'A';// subtract 'A' to get index 0-25
upLetters[index]++;//add one
}
if (ptr[i] >= 'a' && ptr[i] <= 'z') //stores occurrences of lowercase letters
{
index = ptr[i] - 'a';//subtract 'a' to get index 0-25
loLetters[index]++;//add one
}
i++;//next character in ptr
}
printf("Number of Occurrences of Uppercase letters\n\n");
for (i = 0; i < 26; i++)//loop through 0 to 25
{
if (upLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'A'), upLetters[i]);
// add 'A' to go from an index back to a character
}
}
printf("\n");
printf("Number of Occurrences of Lowercase letters\n\n");
for (i = 0; i < 26; i++)
{
if (loLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'a'), loLetters[i]);
// add 'a' to go back from an index to a character
}
}
printf("\n");
}
void findWords(char *point)
{
int i = 0;
int k = 0;
int count = 0;
int j = 0;
int space = 0;
int c = 0;
int len = strlen(point);
char copy[50][100];
char* delim = "{ } . , ( ) ";
char **word;
char *newpoint;
char *newerpoint;
char *token;
int occur[50]; // will store number of occurances of each word
for (; i < 50; i++) //sets all indexes to 0
{
occur[i] = 0;
}
for (i = 0; i < len; i++) //counts # of spaces between words
{
if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
{
space++;
}
}
word = malloc(sizeof(char*)*(space+1)); //allocates memory to array according to number of words
newpoint = malloc(strlen(point)+1);
strcpy(newpoint, point);
newerpoint = malloc(strlen(point) + 1);
strcpy(newerpoint, point);
token = strtok(newpoint, delim);
for (k; k <= space && token != NULL; k++)
{
word[k] = malloc(strlen(token) + 1);
strcpy(word[k], token);
token = strtok(NULL, delim);
printf("%s\n", word[k]);
}
for (k = 0; k <= space; k++)
{
free(word[k]);
}
}
void sort_string(char *p)
{
int c, d = 0, length;
char *pointer, *result, ch;
length = strlen(p);
result = (char*)malloc(length + 1);
pointer = p;
for (ch = 'a'; ch <= 'z'; ch++)
{
for (c = 0; c < length; c++)
{
if (pointer == ch)
{
*(result + d) = *pointer;
d++;
}
pointer++;
}
pointer = p;
}
*(result + d) = '\0';
strcpy(p, result);
free(result);
}
编辑版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void findLetters(char *ptr);
void findWords(char *point);
int compare_str (const void *a, const void *b);
int main (void)
{
char textStream[100] = {0}; //up to 98 characters and '\n\ and '\0'
typedef unsigned int size_t;
size_t len = 0;
printf ("enter some text\n");
if (fgets (textStream, sizeof textStream, stdin)) //input up to 99 characters
{
len = strlen (textStream);
textStream[--len] = 0; // strip newline from end of textStream
findLetters (textStream);
findWords (textStream);
}
else
{
printf("fgets failed\n");
}
return 0;
}
void findLetters(char *ptr) //find occurences of all letters
{
int upLetters[26];
int loLetters[26];
int i;
int index;
for (i = 0; i < 26; i++) // set array to all zero
{
upLetters[i] = 0;
loLetters[i] = 0;
}
i = 0;
while (ptr[i] != '\0') // loop until prt[i] is '\0'
{
if (ptr[i] >= 'A' && ptr[i] <= 'Z') //stores occurrences of uppercase letters
{
index = ptr[i] - 'A';// subtract 'A' to get index 0-25
upLetters[index]++;//add one
}
if (ptr[i] >= 'a' && ptr[i] <= 'z') //stores occurrences of lowercase letters
{
index = ptr[i] - 'a';//subtract 'a' to get index 0-25
loLetters[index]++;//add one
}
i++;//next character in ptr
}
printf("Number of Occurrences of Uppercase letters\n\n");
for (i = 0; i < 26; i++)//loop through 0 to 25
{
if (upLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'A'), upLetters[i]);
// add 'A' to go from an index back to a character
}
}
printf("\n");
printf("Number of Occurrences of Lowercase letters\n\n");
for (i = 0; i < 26; i++)
{
if (loLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'a'), loLetters[i]);
// add 'a' to go back from an index to a character
}
}
printf("\n");
}
void findWords(char *point)
{
int i, k, count, space;
int len = strlen (point);
char *delim = "\n { } . , ( ) ";
char **word = NULL;
char *newpoint = NULL;
char *token = NULL;
i = k = count = space = 0;
for (i = 0; i < len; i++) //counts # of spaces between words
if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
space++;
word = malloc (sizeof *word * space + 1); //allocates memory to array according to number of words
newpoint = malloc (strlen (point) + 1);
strcpy (newpoint, point);
token = strtok (newpoint, delim);
printf ("\nSeparating and saving words in pointer array:\n\n");
for (k = 0; token != NULL; k++)
{
word[k] = malloc (strlen (token) + 1);
strcpy (word[k], token);
token = strtok (NULL, delim);
printf ("%s\n", word[k]);
}
count = k; /* save number of string in word */
qsort (word, count, sizeof *word, compare_str); /* sort the array of pointers */
printf ("\nSorted words in pointer array:\n\n");
for (k = 0; k < count; k++)
printf ("%s\n", word[k]);
for (k = 0; k < count; k++)
{
free(word[k]);
}
}
int compare_str (const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
答案 0 :(得分:2)
当你确实让它发挥作用时,我认为你会感到惊讶。 sort_string
函数与排序指针数组中的单词无关,而是对数组中的字符进行排序。例如:
$ ./bin/str_sort_words
Enter a string: a quick brown fox jumps over the lazy dog
sorted words: aabcdeefghijklmnoooopqrrstuuvwxyz
相反,您需要使用qsort
对指针数组进行排序,以便实际排序单词而不是字符。要使用qsort
,您必须为其提供compare
功能,以便它知道要排序的项目的大小和数量。对于指针数组,qsort
比较函数如下所示:
/* qsort C-string comparison function */
int compare_str (const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
然后在你的情况下,你必须在指针数组findWords
所在的word
函数中调用它,如下所示:
qsort (word, count, sizeof *word, compare_str);
(其中count
是您的space + 1
等效物)。现在,在我们查看答案之前,您需要在编译时启用警告(由于if (pointer == ch)
中的指针/ int不匹配,您的代码不应该是if (*pointer == ch)
findWords
-Wall -Wextra
1}}。
但除此之外,在启用警告的情况下进行编译会在char textStream[100] = {0}; //up to 98 characters and '\n\ and '\0'
size_t len = 0;
中指出一系列问题。要启用警告,请将fgets
添加到编译字符串中。
现在让我们看一下代码的变化。 始终初始化所有变量:
getline
接下来,在使用newline
或if (fgets (textStream, sizeof textStream, stdin)) //input up to 99 characters
{
len = strlen (textStream);
textStream[--len] = 0; // strip newline from end of textStream
...
时,最好剥去拖尾findWords
,以免它悬挂在你的琴弦上:
void findWords(char *point)
{
int i = 0;
int k = 0;
int count = 0;
// int j = 0;
int space = 0;
// int c = 0;
int len = strlen(point);
// char copy[50][100];
char* delim = "{ } . , ( ) ";
char **word = NULL;
char *newpoint = NULL;
char *newerpoint = NULL;
char *token = NULL;
// int occur[50]; // will store number of occurances of each word
//
// for (; i < 50; i++) //sets all indexes to 0
// {
// occur[i] = 0;
// }
for (i = 0; i < len; i++) //counts # of spaces between words
{
if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
{
space++;
}
}
word = malloc (sizeof *word * space + 1); //allocates memory to array according to number of words
newpoint = malloc (strlen (point) + 1);
strcpy (newpoint, point);
newerpoint = malloc (strlen (point) + 1);
strcpy (newerpoint, point);
token = strtok (newpoint, delim);
printf ("\nSeparating and saving words in pointer array:\n\n");
for (k = 0; token != NULL; k++)
{
word[k] = malloc (strlen (token) + 1);
strcpy (word[k], token);
token = strtok (NULL, delim);
printf ("%s\n", word[k]);
}
count = k; /* save number of string in word */
qsort (word, count, sizeof *word, compare_str); /* sort the array of pointers */
printf ("\nSorted words in pointer array:\n\n");
for (k = 0; k < count; k++)
printf ("%s\n", word[k]);
for (k = 0; k < count; k++)
{
free(word[k]);
}
}
现在,更改为gcc -Wall -Wextra -o yourprog yourfile.c
:
$ ./bin/str_find_ltr_words
enter some text
the quick brown fox jumped over a lazy dog
Number of Occurrences of Uppercase letters
Number of Occurrences of Lowercase letters
a : 2
b : 1
c : 1
d : 2
e : 3
f : 1
g : 1
h : 1
i : 1
j : 1
k : 1
l : 1
m : 1
n : 1
o : 4
p : 1
q : 1
r : 2
t : 1
u : 2
v : 1
w : 1
x : 1
y : 1
z : 1
Separating and saving words in pointer array:
the
quick
brown
fox
jumped
over
a
lazy
dog
Sorted words in pointer array:
a
brown
dog
fox
jumped
lazy
over
quick
the
编译时,应该有 NO 警告:
findWords
示例使用/输出
findWords
最后一点。您的#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void findLetters(char *ptr);
void findWords(char *point);
void sort_string(char *p);
int compare_str (const void *a, const void *b);
int main (void)
{
char textStream[100] = {0}; //up to 98 characters and '\n\ and '\0'
size_t len = 0;
printf ("enter some text\n");
if (fgets (textStream, sizeof textStream, stdin)) //input up to 99 characters
{
len = strlen (textStream);
textStream[--len] = 0; // strip newline from end of textStream
findLetters (textStream);
findWords (textStream);
sort_string (textStream);
}
else
{
printf("fgets failed\n");
}
return 0;
}
void findLetters(char *ptr) //find occurences of all letters
{
int upLetters[26];
int loLetters[26];
int i;
int index;
for (i = 0; i < 26; i++) // set array to all zero
{
upLetters[i] = 0;
loLetters[i] = 0;
}
i = 0;
while (ptr[i] != '\0') // loop until prt[i] is '\0'
{
if (ptr[i] >= 'A' && ptr[i] <= 'Z') //stores occurrences of uppercase letters
{
index = ptr[i] - 'A';// subtract 'A' to get index 0-25
upLetters[index]++;//add one
}
if (ptr[i] >= 'a' && ptr[i] <= 'z') //stores occurrences of lowercase letters
{
index = ptr[i] - 'a';//subtract 'a' to get index 0-25
loLetters[index]++;//add one
}
i++;//next character in ptr
}
printf("Number of Occurrences of Uppercase letters\n\n");
for (i = 0; i < 26; i++)//loop through 0 to 25
{
if (upLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'A'), upLetters[i]);
// add 'A' to go from an index back to a character
}
}
printf("\n");
printf("Number of Occurrences of Lowercase letters\n\n");
for (i = 0; i < 26; i++)
{
if (loLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'a'), loLetters[i]);
// add 'a' to go back from an index to a character
}
}
printf("\n");
}
void findWords(char *point)
{
int i, k, count, space;
int len = strlen (point);
char *delim = "{ } . , ( ) \n";
char **word = NULL;
char *newpoint = NULL;
char *token = NULL;
i = k = count = space = 0;
for (i = 0; i < len; i++) //counts # of spaces between words
if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
space++;
word = malloc (sizeof *word * space + 1); //allocates memory to array according to number of words
newpoint = malloc (strlen (point) + 1);
strcpy (newpoint, point);
token = strtok (newpoint, delim);
printf ("\nSeparating and saving words in pointer array:\n\n");
for (k = 0; token != NULL; k++)
{
word[k] = malloc (strlen (token) + 1);
strcpy (word[k], token);
token = strtok (NULL, delim);
printf ("%s\n", word[k]);
}
count = k; /* save number of string in word */
qsort (word, count, sizeof *word, compare_str); /* sort the array of pointers */
printf ("\nSorted words in pointer array:\n\n");
for (k = 0; k < count; k++)
printf ("%s\n", word[k]);
for (k = 0; k < count; k++)
{
free(word[k]);
}
}
void sort_string(char *p)
{
int c, d = 0, length;
char *pointer, *result, ch;
length = strlen(p);
result = (char*)malloc(length + 1);
pointer = p;
for (ch = 'a'; ch <= 'z'; ch++)
{
for (c = 0; c < length; c++)
{
if (*pointer == ch)
{
*(result + d) = *pointer;
d++;
}
pointer++;
}
pointer = p;
}
*(result + d) = '\0';
strcpy(p, result);
free(result);
}
/* qsort C-string comparison function */
int compare_str (const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
函数中存在很多不相关的代码。我没有花时间去除它,因为这并不能阻止你的话。具有上述修改的代码在没有警告的情况下编译。因此,我会留给你去'\n'
然后去掉那些不需要的东西。
完整示例
fgets
为什么你有额外的换行
正如评论和答案中所提到的,当您使用getline
或{阅读时,始终最好从字符串中删除尾随的len
{1}}。这将导致1
中的字符数被space
关闭,然后1
计数将被char* delim = "{ } . , ( ) ";
关闭。既然这本身并不构成犯罪,那么它只会让你分配一个超过需要的指针。但是,由于您的定义,它会产生后果:
'\n'
由于您未指定strtok
作为分隔符,因此textStream
乐意将其视为单独的单词。这会导致您的排序出现问题,因为现在您的单词数组中出现了空行。因此,您可以在阅读'\n'
或将delim
添加到char* delim = "{ } . , ( ) \n";
(或两者都适用)后删除换行符。
strcasecmp
不区分大小写排序
如果想要在没有LOCALE排序大写字母效果的情况下进行排序等,请使用strcmp
代替qsort
。如上所述,只需将int compare_str (const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcasecmp(*ia, *ib);
}
比较更改为:
strcasecmp
Windows上的strcasecmp
stricmp
是Linux上可用的非标准函数,而不是在windows中。要包含相同的功能,请改用{{1}}。见(MSDN stricmp)。