【问题标题】:Cannot get input from user to work in place of manual strings entered in code无法从用户那里获得输入以代替在代码中输入的手动字符串
【发布时间】:2014-04-28 20:58:41
【问题描述】:

我试图让一个程序运行,它基本上接受一个输入字符串并通过一些代码发送它,并使用链表按字母顺序对其进行排序。我已经想出了如何使用手动(在实际代码中)文本输入来完成这项工作,但是当我试图从用户那里获取输入时,我无法让它工作。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct llist {
    char *value;
    struct llist *next;
};

int compare (struct llist *one , struct llist *two)
{
return strcmp(one->value, two->value);
}

void add(struct llist **pp, char *value, int (*cmp)(struct llist *l, struct llist *r)) {

    struct llist *new;
    new = malloc(sizeof(*new));
    new->value = value;

    for ( ; *pp != NULL; pp = &(*pp)->next) {
        if (cmp(*pp, new) > 0 ) break;
        }

    new->next = *pp;
    *pp = new;
}

void display(struct llist *ptr) {

    for (; ptr != NULL; ptr = ptr->next) {
        printf("%s\n", ptr->value);
    }
}

int main(void) {
    struct llist *root = NULL;
    char string;

    printf("Please enter a string to be sorted alphabetically and displayed with a character count: ");
    string = getchar();

    while (string != 10){
    add(&root,&string, compare);
    string = getchar();

    }

    display(root);

    return 0;
}

查看 main 函数,我很确定它与 getchar 以及它以整数形式读取字符的事实有关,但我不知道如何解决这个问题,输出只是一堆空行。但是当while循环被删除并在main中输入如下字符串时,它工作正常吗?为什么会这样?

int main(void) {
    struct llist *root = NULL;
    char string;

    printf("Please enter a string to be sorted alphabetically and displayed with a character count: ");

    add(&root,"t", compare);
    add(&root,"h", compare);
    add(&root,"i", compare);
    add(&root,"s", compare);
    add(&root,"m", compare);
    add(&root,"y", compare);
    add(&root,"t", compare);
    add(&root,"e", compare);
    add(&root,"x", compare);
    add(&root,"t", compare);

    display(root);

    return 0;
}

现在的输出是 e H 一世 米 s 吨 吨 吨 X 是的

这是正确的, 谁能帮我?

【问题讨论】:

  • 注意:为什么使用string != 10而不是string != '\n'
  • 我原来是用那个的,不知道为什么我改了,但是我把它改回来了,因为它确实更有意义
  • 代码通过strcmp()“比较”,它接受字符串。字段value&amp;string 的副本,是一个指向char 但没有'\0' 终止符的指针。
  • 是的,这就是 shf301 所说的,我修复了它,但不幸的是它仍然没有帮助我的输出:/

标签: c string input getchar


【解决方案1】:

当您在示例中写入"t" 时,您将获得一个数组的地址。对于您传递给add 的每个值,该地址都不同。但是,字符串的地址并没有改变,并且每次调用add 时都将new-&gt;value 设置为相同的值。而不是new-&gt;value = value,请尝试new-&gt;value = *value(以及所有必要的相关更改)。

不需要太多更改。请注意,在单个输入字符串之后终止不是很好的行为。一个很好的练习是编写一个析构函数,在第一行之后拆下字符串,然后对下一行进行排序。另一个不错的练习是对传递的参数进行排序,如果没有给出参数,则读取标准输入。

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct llist {
        char value;    /* CHANGE */
        struct llist *next;
};


typedef int (*compar)( struct llist *one , struct llist *two );


int
compare( struct llist *one , struct llist *two )
{
        return tolower( one->value ) > tolower( two->value );  /* CHANGE */
}


void *
xmalloc( size_t s )
{
        void *v = malloc( s );
        if( v == NULL ) {
                perror( "malloc" );
                exit( EXIT_FAILURE );
        }
        return v;
}


void
add( struct llist **pp, char value, compar cmp ) /* CHANGE */
{

        struct llist *new;
        new = xmalloc( sizeof *new );  /* Check for errors */
        new->value = value;  /* CHANGE the type of value above */

        for( ; *pp != NULL; pp = &(*pp)->next ) {
                if( cmp( *pp, new ) > 0 )
                        break;
        }

        new->next = *pp;
        *pp = new;
}

void
display( struct llist *ptr )
{
        for( ; ptr != NULL; ptr = ptr->next ) {
                putchar( ptr->value );  /* CHANGE */
        }
        putchar( '\n' );
}

int
main( void )
{
        struct llist *root = NULL;
        char string;

        while( (string = getchar()) != '\n' ) {  /* Optional CHANGE (1) */
                add( &root,string, compare );
        }

        display(root);
        return 0;
}

/* 
 * (1) Using "'\n'" instead of 10 is necessary for readability,
 * portability, and sanity of future maintainers.
 * 
 * Writing getchar() only once is cleaner.
 */

【讨论】:

  • 我不知道我是否在关注你,如果是这种情况,我不应该看到打印出相同的字符但只是重复代替我的字符串中的其他字符吗?
  • 没有。您将 char 的地址传递给 strcmp,它需要一个字符串(一个以 null 结尾的 char 数组),所以您有 u.b.
【解决方案2】:

使用硬编码的输入代码,您将字符串传递给add,而在您的用户输入代码中,您只传递一个指向单个字符的指针。 char* 在 C 中不一定是字符串,它可能指向一个字符串,但不一定非要如此。

在 C 中,字符串是一个以空零结尾的字符缓冲区,即字符 '\0'(通常只是值 0)。当您使用 getchar 时,您正在传递一个指向字符的指针 - 并且该字符后面没有空零,因此它不是有效的 C 字符串。

如果您想使用getchar 保留您的代码,您需要使用一个缓冲区,该缓冲区将在该字符之后存储一个空零。您可以对一个小数组执行此操作,如下所示:

int main(void) {
    struct llist *root = NULL;
    char string[2];

    string[1] = '\0'; // Ensure that we have a null terminated string

    printf("Please enter a string to be sorted alphabetically and displayed with a character count: ");
    string[0] = getchar();

    while (string != '\n'){
    add(&root,string, compare);
    string[0] = getchar();

    }

    display(root);

    return 0;
}

【讨论】:

  • 好的我明白你在说什么,但现在字符串将是一个字符指针,我将它与'while(string!='\n')'中的整数值进行比较,所以我将其更改为 'while (string[0] != '\n')' 并编译,但仍然遇到相同的错误,只有空格。
【解决方案3】:

清理了一些东西

1) 作为@shf301 siad,需要传递一个字符串,而不仅仅是指向单个char的指针。

2) 需要创建字符串的副本 - 通知 strdup

3) While 循环应该在'\nEO 以及'\0 上中断。 getchar() 出于某种原因返回 intEOF0UCHAR_MAX(例如 255)。

4) free() 资源是否应该在末尾 - 未显示。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// In case you library does not have strdup() ...
char *strdup(const char *s) {
  if (s == NULL) return NULL;
  size_t siz = strlen(s) + 1;
  char *y = malloc(siz);
  if (y != NULL) {
    memcpy(y, s, siz);
  }
  return y;
}

struct llist {
  char *value;
  struct llist *next;
};

int compare(struct llist *one, struct llist *two) {
  return strcmp(one->value, two->value);
}

void add(struct llist **pp, char *value,
        int(*cmp)(struct llist *l, struct llist *r)) {

  struct llist *new;
  new = malloc(sizeof(*new));
  new->value = strdup(value);

  for (; *pp != NULL; pp = &(*pp)->next) {
    if (cmp(*pp, new) > 0)
      break;
  }

  new->next = *pp;
  *pp = new;
}

void display(const struct llist *ptr) {

  for (; ptr != NULL; ptr = ptr->next) {
    printf("%s\n", ptr->value);
  }
}

int main(void) {
  struct llist *root = NULL;
  char string[2];
  string[1] = '\0';

  printf("Please enter a string to be sorted alphabetically"
          " and displayed with a character count: ");

  int ch;
  while ((ch = getchar()) != EOF && ch != '\n' && ch != '\0') {
    string[0] = ch;
    add(&root, string, compare);
  }

  display(root);

  return 0;
}

【讨论】:

  • 天哪,它起作用了....所以一切都归结为stdup?我以前从未听说过。你用 ch 做的事情是有道理的,但我从来没想过要把它变成一个 int ,我猜它是有道理的。非常感谢 Chux!
  • 一段时间后(几分钟到几天),如果一个答案很好地满足您的需求,接受它。一旦您获得 15 分以上的积分,请务必对任何对您有帮助的答案进行投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
相关资源
最近更新 更多