所以我的任务是从char数组删除这些以相同字母开头和结尾的单词。此时我的程序崩溃了。 这是我的功能:
void RemoveSame(char * start) {
int i, j, first, last, k;
for (i = 1; i < LINE_LENGTH; i++) {
if ( * (start + i) != ' ') {
first = * (start + i);
for (j = i; j < LINE_LENGTH; j++) {
if ( * (start + i + j + 1) == ' ') {
last = * (start + i + j);
} else {
break;
}
}
}
for (; i != j; i++) {
k = j - i;
* (start + k) = "\0";
}
}
}
这是我的完整代码http://pasted.co/22566eb6
答案 0 :(得分:1)
正如其他人所说:
将* (start + i)
更改为start[i]
可提高可读性
"\0"
应该是'\0'
或者只是0 - 在c中,双引号用于表示字符串,而字符串实际上是内存地址。
数组索引从0开始
还要记住,源代码中明确写入的字符串(例如:“abcba this is a string”)是常量字符串(const char *),必须复制到其他位置才能修改它们。
void RemoveSame(char * start) {
int i, j, k;
for (i = 0; start[i];) { // advance while haven't reached the string's end
if (start[i] != ' ') {
for (j = i + 1; ; ++j) {
if (start[j] == ' ' || !start[j]) { // advance until I find a word
if (start[i] == start[j - 1]) {
for (k = i; (start[k] = start[k + j - i]); ++k); // delete word
}
else {
i = j;
}
break;
}
}
}
else {
++i;
}
}
}
答案 1 :(得分:1)
对于初学者来说,代码格式太差,很难理解它的作用。
目前尚不清楚为什么外环从1开始。 内环
for (j = i; j < LINE_LENGTH; j++) {
if ( * (start + i + j + 1) == ' ') {
last = * (start + i + j);
} else {
break;
}
}
没有任何意义。
此循环
for (; i != j; i++) {
k = j - i;
* (start + k) = "\0";
}
也没有意义,而且在此声明中
* (start + k) = "\0";
您正尝试为char
类型的对象分配值char *
的值。编译器应在此处发出诊断消息。
还不清楚为什么不使用标准C函数。
该功能可以按照以下方式查看,如本演示程序中所示
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define N 100
char * remove_words( char *s )
{
size_t n = strlen( s );
char *t = s;
while ( *t )
{
while ( isblank( ( unsigned char )*t ) ) ++t;
char *last = t;
if ( *last++ )
{
while ( *last && !isblank( ( unsigned char )*last ) ) ++last;
if ( t[0] == last[-1] ) memmove( t, last, n - ( last -t ) + 1 );
else t = last;
}
}
return s;
}
int main( void )
{
while ( 1 )
{
char s[N];
printf( "Input a sentence: (Enter - exit): " );
if ( fgets( s, sizeof( s ), stdin ) == NULL || s[0] == '\n' ) break;
s[ strcspn( s, "\n") ] = '\0';
puts( s );
puts( remove_words( s ) );
printf( "\n" );
}
return 0;
}
它的输出可能看起来像
Input a sentence: (Enter - exit): ab aba abc abcbca dd d
ab aba abc abcbca dd d
ab abc
Input a sentence: (Enter - exit):
另一种方法是删除必须删除的单词后面的空格。它比第一种方法更有效。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define N 100
char * remove_words( char *s )
{
char *destination = s;
// for starters skip leading blands
while ( isblank( ( unsigned char )*destination ) ) ++destination;
char *source = destination;
while ( *source )
{
char *last = source;
if ( *last++ )
{
while ( *last && !isblank( ( unsigned char )*last ) ) ++last;
char *blank_tail = last;
while ( isblank( ( unsigned char )*blank_tail ) ) ++blank_tail;
if ( source[0] != last[-1] )
{
// copy valid word to the destination
if ( destination != source )
{
memmove( destination, source, blank_tail - source );
}
destination += blank_tail - source;
}
source = blank_tail;
}
}
*destination = '\0';
return s;
}
int main( void )
{
while ( 1 )
{
char s[N];
printf( "Input a sentence: (Enter - exit): " );
if ( fgets( s, sizeof( s ), stdin ) == NULL || s[0] == '\n' ) break;
s[ strcspn( s, "\n") ] = '\0';
puts( s );
puts( remove_words( s ) );
printf( "\n" );
}
return 0;
}
程序输出可能与abobe显示的方式相同
Input a sentence: (Enter - exit): ab aba abc abcbca dd d
ab aba abc abcbca dd d
ab abc
Input a sentence: (Enter - exit):
答案 2 :(得分:0)
#include <stdio.h>
#include <ctype.h>
char *RemoveSame(char *str) {
char *from, *to, *p;
from = to = str;
while(*from){
if(isspace((unsigned char)*from)){//pre spaces copy before processing a word
*to++ = *from++;
continue;
}
p = from;//top of word
while(*p && !isspace((unsigned char)*p))
++p;
if(*from == p[-1])//top == end
from = p;//skip
else {
while(*from && !isspace((unsigned char)*from))
*to++ = *from++;//copy
}
}
*to = 0;
return str;
}
int main(void) {
char sentence[] = "madam adam madam ada adam eve";
printf("'%s'\n", RemoveSame(sentence));
}
答案 3 :(得分:0)
您的函数RemoveSame()
有多个问题:
i
应从0
j
应从1
开始。您使用start[i + j + 1]
你应该停在'\0'
您永远不会复制您希望保留的字词
将字符串的其余部分设置为0
似乎没必要,但无论如何你应该使用空字符'\0'
而不是空字符串"\0"
以下是更正后的版本:
void RemoveSame(char *str) {
int i, j, to = 0;
for (i = 0; str[i] != '\0';) {
if (str[i] == ' ') {
str[to++] = str[i++];
continue;
}
for (j = 1; str[i + j] != '\0'; j++) {
if (str[i + j] == ' ')
break;
}
if (str[i] == str[i + j - 1]) {
/* skip the word */
i += j;
continue;
}
for (; j > 0; j--) {
str[to++] = str[i++];
}
}
str[to] = '\0'; /* set the null terminator */
}
注意:
str
是字符串比start
更明确的名称。
使用数组表示法str[i]
比*(str + i)
更具可读性。
删除的单词之前或之后的空格也应该被移除。
您的代码中还有其他问题:
scanf("%s", &readerName);
不正确,请改用scanf("%s", readerName);
。
以这种方式分配line
:line = calloc(FILE_NAME_LENGTH, FILE_NAME_LENGTH * sizeof(char))
不正确,请使用自动数组:char line[LINE_LENGTH];
while (!feof(reader))
总是错的。请改用while (fgets(line, LINE_LENGTH, reader))
。
WriteLine()
应停在第一个'\0'
。
您应该使用'\0'
作为空字符,而不是NULL
*(start + i) != NULL