Objective c 如何更改此程序的输入?(C语言)

Objective c 如何更改此程序的输入?(C语言),objective-c,c,Objective C,C,如何用(scanf)替换(FILE)和(fopen)来获取输入值并发送这两个函数 我想在Objective-c代码中使用这个函数。 有关更多信息,您可以在此处查看整个代码 static void stemfile(文件*f) {while(TRUE) {int ch=getc(f); 如果(ch==EOF)返回; if(字母(ch)) {int i=0; while(TRUE) {如果(i==i_max)增加_s(); ch=下压(ch);/*强制下压*/ s[i]=ch;i++; ch=get

如何用(scanf)替换(FILE)和(fopen)来获取输入值并发送这两个函数

我想在Objective-c代码中使用这个函数。 有关更多信息,您可以在此处查看整个代码

static void stemfile(文件*f)
{while(TRUE)
{int ch=getc(f);
如果(ch==EOF)返回;
if(字母(ch))
{int i=0;
while(TRUE)
{如果(i==i_max)增加_s();
ch=下压(ch);/*强制下压*/
s[i]=ch;i++;
ch=getc(f);
如果(!LETTER(ch)){ungetc(ch,f);break;}
}
s[茎(s,0,i-1)+1]=0;
/*前一行调用词干分析器并使用其结果
零终止s中的字符串*/
printf(“%s”,s);
}
else-putchar(ch);
}
}
int main(int argc,char*argv[])
{int i;
s=(char*)malloc(i_max+1);
对于(i=1;i
函数不能直接替换现有代码。现有代码(在IMO中编写得不是很好)将输入字符流拆分为字母(由
LETTER()
宏定义为大写或小写字符)和非字母,并在对其应用
stem()
函数之前将这些字母序列转换为小写

另一方面,
scanf()
函数从输入流中提取基本类型(int、char、double等)和显式分隔的字符串。给定代码中的分隔符(即任何不是
字母()
)对于
scanf()
scanf()
需要在子字符串的每一端查找一个特定字符。而且,
scanf()
无法自动转换为小写

假设您的输入仍然是文件,我认为最简单的解决方案可能是让代码保持原样并使用它,尽管它可能很复杂。它没有什么不应该作为更大的Objective-C程序的一部分运行的。毕竟,Objective-C仍然提供对C标准库的访问,至少在操作系统设置的限制范围内(如果您在苹果平台上,iOS比MacOS限制更大)


这里的一般问题是标记化:将未分类符号(如字符)的输入序列分解为分类标记(如单词和空格)序列。解决此问题的常见方法是使用(FSA/FSM)将解析逻辑应用于输入序列,并在遇到令牌时提取它们。设置FSA可能有点困难,但它非常健壮且通用。

我仍然不确定您为什么要在
main()
中使用
scanf()
。这可能意味着将
stemfile()
的接口(包括名称,因为它将不再处理文件)更改为以字符串作为输入。而且
scanf()
会让生活变得困难;它将读取由空格分隔的字符串,这可能是它吸引人的一部分,但它将包括“单词”中包含的任何标点符号

正如Randall所指出的,现有函数中的代码有点陈旧;我认为可以更简单地写如下:

#include <stdio.h>
#include <ctype.h>
#define LETTER(x) isalpha(x)

extern int stem(char *s, int lo, int hi);

static void stemfile(FILE * f)
{
    int ch;
    while ((ch = getc(f)) != EOF)
    {
        if (LETTER(ch))
        {
            char s[1024];
            int i = 0;
            s[i++] = ch; 
            while ((ch = getc(f)) != EOF && LETTER(ch))
                s[i++] = ch;
            if (ch != EOF)
                ungetc(ch, f);
            s[i] = '\0';
            s[stem(s, 0, i-1)+1] = 0;
            /* the previous line calls the stemmer and uses its result to
               zero-terminate the string in s */
            printf("%s", s);
        }
        else
            putchar(ch);
    }
}
这将系统地将
getc(f)
更改为
*src++
EOF
更改为
\0
,并将
ungetc()
更改为
src--
。它还(安全地)将
ch
的类型从
int
(I/O所需)更改为
char
。如果您担心缓冲区溢出,您必须在函数中更加努力地工作,但实际上很少有字会是1024字节(您可以使用4096和1024字节一样简单,实际数据溢出缓冲区的可能性相对较小(非常小)。您需要判断这是否是“真正”的风险

主程序可以变得非常简单:

int main(void)
{
    char string[1024];
    while (scanf("%1023s", string) == 1)
        stemstring(string);
    return(0);
}
显然,由于格式中的“1023”,这将永远不会溢出内部缓冲区。(注意:在本答案的第一个版本中,从
“%.1023s”
中删除了
scanf()
printf()
!)不同)


挑战:这有用吗

是-下面的代码(添加一个伪
stem()
函数并稍微修改打印)对我来说相当有效:

#include <stdio.h>
#include <ctype.h>
#include <assert.h>

#define LETTER(x) isalpha(x)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))

static int stem(const char *s, int begin, int end)
{
    assert(s != 0);
    return MAX(end - begin - 3, 3);
}

static void stemstring(const char *src)
{
    char ch;
    while ((ch = *src++) != '\0')
    {
        if (LETTER(ch))
        {
            int i = 0;
            char s[1024];
            s[i++] = ch;
            while ((ch = *src++) != '\0' && LETTER(ch))
                s[i++] = ch;
            if (ch != '\0')
                src--;
            s[i-1] = '\0';
            s[stem(s,0,i-1)+1] = 0;
            /* the previous line calls the stemmer and uses its result to
               zero-terminate the string in s */
            printf("<<%s>>\n",s);
        }
        else
            putchar(ch);
    }
    putchar('\n');
}

int main(void)
{
    char string[1024];
    while (scanf("%1023s", string) == 1)
        stemstring(string);
    return(0);
}
显示带调试的输出(第一行是键入的输入;其余是程序的输出):

这是一本多么伟大的书啊!你做了什么? -->>干管柱: LP 道路(4) ST(0,3)RV 4 RS 干管柱: LP 道路发展(1) ST(0,0)RV 1 RS 干管柱: LP 道路(5) ST(0,4)RV 5 RS 干管柱: LP 道路(4) ST(0,3)RV 4 RS 干管柱: LP 道路(4) ST(0,3)RV 4 RS 干管柱: LP 道路(2) ST(0,1)RV 2 RS LP NL 干管柱: LP 道路(4) ST(0,3)RV 4 RS LP NL LP 道路(4) ST(0,3)RV 4 RS LP NL LP 道路(4) ST(0,3)RV 4 RS LP NL LP 道路(4) ST(0,3)RV 4 RS LP>
您必须更仔细地解释约束。您想在哪里使用
scanf()
(以及为什么要使用它)?但是,您必须明确地将
stdin
指定为
ungetch()
。您的版本使用了一个
文件*
参数,这通常意味着“更好”。谢谢,在主函数中,我想使用scanf而不是fopen。非常感谢您花了这么多时间进行此修订,实际上原始代码在控制台中工作,但我想在我的Objective C中的应用程序中使用它程序,我需要给这个算法一个带有ED或TION或ER后缀的单词,并接收动词本身,这就是为什么我想用这种方式更改它!当我运行代码时,它有错误!(未知
int main(void)
{
    char string[1024];
    while (scanf("%1023s", string) == 1)
        stemstring(string);
    return(0);
}
#include <stdio.h>
#include <ctype.h>
#include <assert.h>

#define LETTER(x) isalpha(x)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))

static int stem(const char *s, int begin, int end)
{
    assert(s != 0);
    return MAX(end - begin - 3, 3);
}

static void stemstring(const char *src)
{
    char ch;
    while ((ch = *src++) != '\0')
    {
        if (LETTER(ch))
        {
            int i = 0;
            char s[1024];
            s[i++] = ch;
            while ((ch = *src++) != '\0' && LETTER(ch))
                s[i++] = ch;
            if (ch != '\0')
                src--;
            s[i-1] = '\0';
            s[stem(s,0,i-1)+1] = 0;
            /* the previous line calls the stemmer and uses its result to
               zero-terminate the string in s */
            printf("<<%s>>\n",s);
        }
        else
            putchar(ch);
    }
    putchar('\n');
}

int main(void)
{
    char string[1024];
    while (scanf("%1023s", string) == 1)
        stemstring(string);
    return(0);
}
H:  assda23
C:  <<assd>>
C:  23
H:  3423///asdrrrf12312
C:  3423///<<asdr>>
C:  12312
H:  12//as//12
C:  12//<<a>>
C:  //12
#include <stdio.h>
#include <ctype.h>
#include <assert.h>

#define LETTER(x) isalpha(x)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))

static int stem(const char *s, int begin, int end)
{
    int len = end - begin + 1;
    assert(s != 0);
    printf("ST (%d,%d) <<%*.*s>> RV %d\n", begin, end, len, len, s, len);
//    return MAX(end - begin - 3, 3);
    return len;
}

static void stemstring(const char *src)
{
    char ch;
    printf("-->> stemstring: <<%s>>\n", src);
    while ((ch = *src++) != '\0')
    {
        if (ch != '\0')
            printf("LP <<%c%s>>\n", ch, src);
        if (LETTER(ch))
        {
            int i = 0;
            char s[1024];
            s[i++] = ch;
            while ((ch = *src++) != '\0' && LETTER(ch))
                s[i++] = ch;
            src--;
            s[i] = '\0';
            printf("RD (%d) <<%s>>\n", i, s);
            s[stem(s, 0, i-1)+1] = '\0';
            /* the previous line calls the stemmer and uses its result to
               zero-terminate the string in s */
            printf("RS <<%s>>\n", s);
        }
        else
            printf("NL <<%c>>\n", ch);
    }
    //putchar('\n');
    printf("<<-- stemstring\n");
}

int main(void)
{
    char string[1024];
    while (scanf("%1023s", string) == 1)
        stemstring(string);
    return(0);
}
what a great book this is! What.hast.thou.done?
-->> stemstring: <<what>>
LP <<what>>
RD (4) <<what>>
ST (0,3) <<what>> RV 4
RS <<what>>
<<-- stemstring
-->> stemstring: <<a>>
LP <<a>>
RD (1) <<a>>
ST (0,0) <<a>> RV 1
RS <<a>>
<<-- stemstring
-->> stemstring: <<great>>
LP <<great>>
RD (5) <<great>>
ST (0,4) <<great>> RV 5
RS <<great>>
<<-- stemstring
-->> stemstring: <<book>>
LP <<book>>
RD (4) <<book>>
ST (0,3) <<book>> RV 4
RS <<book>>
<<-- stemstring
-->> stemstring: <<this>>
LP <<this>>
RD (4) <<this>>
ST (0,3) <<this>> RV 4
RS <<this>>
<<-- stemstring
-->> stemstring: <<is!>>
LP <<is!>>
RD (2) <<is>>
ST (0,1) <<is>> RV 2
RS <<is>>
LP <<!>>
NL <<!>>
<<-- stemstring
-->> stemstring: <<What.hast.thou.done?>>
LP <<What.hast.thou.done?>>
RD (4) <<What>>
ST (0,3) <<What>> RV 4
RS <<What>>
LP <<.hast.thou.done?>>
NL <<.>>
LP <<hast.thou.done?>>
RD (4) <<hast>>
ST (0,3) <<hast>> RV 4
RS <<hast>>
LP <<.thou.done?>>
NL <<.>>
LP <<thou.done?>>
RD (4) <<thou>>
ST (0,3) <<thou>> RV 4
RS <<thou>>
LP <<.done?>>
NL <<.>>
LP <<done?>>
RD (4) <<done>>
ST (0,3) <<done>> RV 4
RS <<done>>
LP <<?>>
NL <<?>>
<<-- stemstring