【问题标题】:Why doesn't my shell program open the file it received as argument in function "cat"为什么我的 shell 程序不打开它作为函数“cat”中的参数接收的文件
【发布时间】:2011-11-17 17:47:53
【问题描述】:

我在下面包含了代码,很抱歉用这么多代码打扰您。参数解析没问题,我用手表检查了一下。我放了一些printfs 来检查问题可能出在哪里,它似乎没有打开cat 作为参数接收的文件。它在 shell 中被称为“cat -b file

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

#define TRUE 0
#define FALSE 1

void yes(int argc, char *argv[]);
int cat(int argc, char *argv[]);

//#include "cat.h"
//#include "yes.h"
//#include"tee.h"

char buf[50],c[10], *p2,*p, *pch;

int count;
char *matrix[20];

void yes(int argc, char *argv[])
{
    int i;
// if (argc >= 2 && *argv[1] == '-')
    //  {
    //printf("ERROR!");
    //}
    //if (argc == 1)
    // {
    while (1)
        if (puts("y") == EOF)
        {
            perror("yes");
            exit(FALSE);
        }
    // }

    while (1)
        for (i = 1; i < argc; i++)
            if (fputs(argv[i], stdout) == EOF || putchar(i == argc - 1 ? '\n' : ' ') == EOF)
            {
                perror("yes");
                exit(FALSE);
            }
    //exit(TRUE);
}



int main(int argc, char *argv[])
{
    //p=(char *)malloc(sizeof(char)*50);
    do
    {
        fprintf (stderr, "$ ");
        fgets (buf,50,stdin);
        p=buf;
        fprintf (stderr, "Comanda primita de la tastatura: ");
        fputs (buf, stderr);
        int i=0,j=0;
        //strcpy(p,buf);
        strcpy(c,"\0");
        while (buf[i] == ' ')
        {
            i++;
            p++;
        }
        if (buf[i] == '#')
            fprintf (stderr, "Nici o comanda, ci e un comentariu!\n");
        else
        {
            j=0;
            while (buf[i] != ' ' && buf[i] != '\n')
            {
                i++;
                j++;
            }
            strncpy (c,p,j);
            fprintf (stderr, "%s\n",c);
            if (strcmp (c,"yes") == 0)
            {
                p2 = p+j+1;
                pch = strtok (p2," ");
                count = 0;
                while (pch != NULL)
                {
                    //printf ("%s\n",pch);
                    matrix[count] = strdup(pch);
                    pch = strtok (NULL, " ");
                    count++;
                }
                yes(count, matrix);
                fprintf (stderr, "Aici se va executa comanda yes\n");
            }
            else if (strcmp (c,"cat") == 0)
            {
                p2 = p+j+1;
                pch = strtok (p2," ");
                count = 0;
                while (pch != NULL)
                {
                    //printf ("%s\n",pch);
                    matrix[count] = strdup(pch);
                    pch = strtok (NULL, " ");
                    count++;
                }
                cat(count,matrix);
                fprintf (stderr, "Aici se va executa comanda cat \n");
            }
            else if (strcmp (c,"tee") == 0)
            {
                //tee();
                fprintf(stderr, "Aici se va executa comanda tee\n");
            }


            fprintf (stderr, "Aici se va executa comanda basename\n");

            strcpy(buf,"\0");
        }
    }
    while (strcmp(c, "exit") != 0);
    fprintf (stderr, "Terminat corect!\n");
    return 0;
}
int cat(int argc, char *argv[])
{
    int c ;

    opterr = 0 ;
    optind = 0 ;

    char number = 0;
    char squeeze = 0;
    char marker = 0;

    fprintf(stderr,"SALUT< SUNT IN FUNCTIZE>\n");
    while ((c = getopt (argc, argv, "bnsE")) != -1)
        switch (c)
        {
        case 'b' :
            number = 1;
            break;
        case 'n' :
            number = 2;
            break;
        case 'm' :
            marker = 1;
            break;
        case 's' :
            squeeze = 1;
            break;
        case 'E' :
            marker = 1;
            break;
        }
    if (optind + 1 != argc)
    {
        fprintf (stderr, "\tWrong arguments!\n") ;
        return -1 ;
    }

    FILE * fd = fopen (argv[optind], "r");
    printf("am deschis fisierul %s ",argv[optind]);
    if (fd == NULL)
    {
        printf("FISIER NULL asdasdasdasdasd");
        return 1;
    }

    char line[1025];
    int line_count = 1;

    while (!feof(fd))
    {
        fgets(line, 1025, fd);
        printf("sunt in while :> %s",line);
        int len = strlen(line);
        if (line[len - 1] == '\n')
        {
            if(len - 2 >= 0)
            {
                if(line[len - 2] == '\r')
                {
                    line[len - 2] = '\0';
                    len -= 2;
                }
                else
                {
                    line[len - 1] = '\0';
                    len -= 1;
                }
            }
            else
            {
                line[len - 1] = '\0';
                len -= 1;
            }
        }

        if (squeeze == 1 && len == 0)
            continue;
        if (number == 1)
        {
            fprintf (stdout, "%4d ", line_count);
            line_count++;
        }
        else if (number == 2)
        {
            if (len > 0)
            {
                fprintf (stdout, "%4d ", line_count);
                line_count++;
            }
            else
                fprintf (stdout, "     ");
        }
        fprintf(stdout, "%s", line);
        if (marker == 1)
            fprintf(stdout, "$");
        fprintf(stdout, "\n");
    }

    fclose (fd);

    return 0 ;
}

【问题讨论】:

  • 执行此操作时屏幕上打印的具体信息是什么?
  • 你如何运行这个程序..?你在命令行参数中传递了什么?
  • 尝试打印 matrix[optind] 的内容,看看它是否确实是你的文件名。
  • 你在说什么cat?正常命令、你的函数或你在这个 mini-shell 中调用时执行的函数?
  • mini-shell 中的函数 cat。

标签: c shell cat


【解决方案1】:

问题是当您使用fgets 时,它会将换行符包含在字符串中。因此,当您传递文件名时,它会附加一个\n 字符,该字符是在输入命令时输入的。所以传递的文件名不正确。乘坐新线路可能在这些线路上(只是一个指针):

char *filename = strtok(argv[optind], "\n");
if( filename == NULL)
{
   /*What the .... */
   Handle error!
}
FILE * fd = fopen (filename, "r");
printf("am deschis fisierul %s ",argv[optind]);
if (fd == NULL)
{
    printf("FISIER NULL asdasdasdasdasd");
    return 1;
}

希望这会有所帮助!

PS:调试过程
fopen 失败时,它会设置errno。要获得确切的错误,请使用 strerror(errno);perror。所以在if(fd == NULL) 中添加perror("fopen"); 显示fopen : No such file or directory。接下来将文件名打印为fprintf(stderr, "\n |%s|\n", argv[optind]); 显示带有换行符的文件名,即

|hello.txt  
|

...然后看到fgets。啊!从那里开始的新行

【讨论】:

  • 噢噢噢,你的眼光好,知识渊博,我有时利用 fgets 在字符串中包含 \n 的优势。真的非常感谢!并感谢您提供错误提示。我会好好利用它。再次感谢,非常感谢!
猜你喜欢
  • 2017-08-18
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 2020-07-07
  • 2021-02-10
相关资源
最近更新 更多