为什么代码没有按预期运行?
这个
char *array[5];
是5 字符指针的数组。在for 循环中,您将字符串复制到未分配的指针,这是未定义的行为。
即使您为array 指针分配内存,由于以下原因,您的程序输出也不会如您所愿:
原因没有。 1:
这里
for (int i = 0; i < 4; i++) {
您只复制了 4 子字符串,但输入字符串具有由空格 (' ') 字符分隔的 5 子字符串。输出将丢失最后一个子字符串。
原因没有。 2:
在strncpy 中复制时,起始偏移量包括空格前的子字符串,因为breakPoints 数组保留了有关给定输入字符串中空格位置的信息。
按照您编写代码的方式,输入字符串必须有一个空格(分隔符)作为第一个字符,因为在复制子字符串时,您正在将字符从当前处理 breakpoints 数组元素复制到下一个 @ 987654333@ 元素。如果字符串开头没有空格(分隔符),breakpoints 数组的第一个元素将是给定字符串第一个单词之后的第一个空格的位置。
您不需要另一个数组来保存给定输入字符串中有关空格(分隔符)的信息。您可以使用strpbrk() 找出下一个分隔符并将子字符串从当前位置复制到下一个分隔符位置,前提是当前位置指向给定字符串中单词的开头。
你可以这样做:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_WORDS 100
char * alloc_str (const char * start, const char * end) {
if (!start || !end || (start >= end)) {
return NULL;
}
char * tmp = malloc (end - start + 1);
if (tmp) {
strncpy (tmp, start, end - start);
tmp[end - start] = '\0';
} else {
fprintf (stderr, "Failed to allocate memory\n");
exit (EXIT_FAILURE);
}
return tmp;
}
void dealloc_str (char ** p_substr) {
if (p_substr) {
for (int i = 0; p_substr[i]; ++i) {
free (p_substr[i]);
p_substr[i] = NULL;
}
}
}
int main (void) {
char string[] = " Joe James John Maria Micheal";
char * p_substr[MAX_WORDS + 1] = {0};
char * p_curr = string;
const char * sep = " ";
unsigned int word_cnt = 0;
while (p_curr && *p_curr) {
char * p_next;
// skip separator
p_curr += strspn(p_curr, sep);
p_next = p_curr;
// find separator
p_next = strpbrk (p_next, sep);
// strpbrk() returns null pointer if no such character
// exists in the input string which is part of string pointed by sep
if (!p_next) {
p_next = p_curr + strlen (p_curr);
}
p_substr[word_cnt] = alloc_str (p_curr, p_next);
if (p_substr[word_cnt]) {
word_cnt++;
}
p_curr = p_next;
}
p_substr[word_cnt] = NULL;
printf ("Number of words in input string : %u\n", word_cnt);
for (int i = 0; p_substr[i]; ++i) {
printf ("%d. %s\n", i + 1, p_substr[i]);
}
dealloc_str (p_substr);
return 0;
}
输出:
# ./a.out
Number of words in input string : 5
1. Joe
2. James
3. John
4. Maria
5. Micheal
如果您想根据多个分隔符拆分字符串,例如- " !,",那么在上面的代码中,只需将" !,"分配给sep即可。