使用system("cls")后出现乱码

kmsch 2016-01-12 05:33:20
VS中,我程序使用freopen重定向到文本,之后恢复重定向,之后调用system("cls"),之后在输出就是乱码

以下代码我提出了关键部分(很短),求帮测试


#include<stdio.h>
#include <windows.h>
void main() {
char szOutputPath[MAX_PATH + 1] = "c:\\123.txt";
freopen(szOutputPath, "w", stdout); //重定向
freopen("con", "w", stdout); //恢复重定向
system("cls"); //执行这条语句后,下一条输出的是乱码,否则正常,注释后正常
printf("11\n22\n33\n");
getchar();
}




...全文
716 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-01-14
  • 打赏
  • 举报
回复
再供参考:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
pid_t rw_popen(char* cmd, FILE **rfile, FILE **wfile) {
    int pipefd[2],pipefd2[2]; //管道描述符
    pid_t pid; //进程描述符

    if (pipe(pipefd) < 0) //建立管道
    {
        printf("rw_popen() pipe create error/n");
        return 0;
    }
    if (pipe(pipefd2) < 0) //建立管道
    {
        printf("rw_popen() pipe create error/n");
        return 0;
    }

    pid = fork(); //建立子进程

    if (pid < 0)
    return 0;

    if (0 == pid) //子进程中
    {
        close(pipefd[0]);
        dup2(pipefd[1], 1);
        close(pipefd[1]);
        dup2(pipefd2[0], 0);
        close(pipefd2[0]);
        close(pipefd[1]);
        char *argv[] = { "/bin/sh", "-c", cmd, NULL };
        if (execvp("/bin/sh", argv) < 0) //用exec族函数执行命令
        exit(1);
    }

    close(pipefd[1]);
    *rfile = fdopen(pipefd[0], "r");
    close(pipefd2[0]);
    *wfile = fdopen(pipefd2[1], "w");
    return pid;
}
void rw_pclose(pid_t pid, FILE *rfile, FILE *wfile) {
    int status;
    waitpid(pid, &status, 0);
    fclose(rfile);
    fclose(wfile);
}
int main() {
    char buf1[1024];
    FILE *file1, *file2;
    pid_t pid;
    pid = rw_popen("sh", &file1, &file2);
    if (pid) {
        fputs("pwd;exit;\n",file2);
        fflush(file2);
        if (fgets(buf1, 1400, file1)) {
            puts(buf1);
        }
        rw_pclose(pid, file1, file2);
    }
    return 1;
}

赵4老师 2016-01-14
  • 打赏
  • 举报
回复
仅供参考:
#pragma comment(lib,"user32")
#include <stdio.h>
#include <windows.h>
int main() {
    SECURITY_ATTRIBUTES sa          = {0};
    STARTUPINFO         si          = {0};
    PROCESS_INFORMATION pi          = {0};
    HANDLE              hPipeOutputRead  = NULL;
    HANDLE              hPipeOutputWrite = NULL;
    HANDLE              hPipeInputRead   = NULL;
    HANDLE              hPipeInputWrite  = NULL;
    BOOL                bTest = 0;
    DWORD               dwNumberOfBytesRead = 0;
    DWORD               dwNumberOfBytesWrite = 0;
    CHAR                szMsg[100];
    CHAR                szBuffer[256];

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    // Create pipe for standard output redirection.
    CreatePipe(&hPipeOutputRead,  // read handle
            &hPipeOutputWrite, // write handle
            &sa,      // security attributes
            0      // number of bytes reserved for pipe - 0 default
            );

    // Create pipe for standard input redirection.
    CreatePipe(&hPipeInputRead,  // read handle
            &hPipeInputWrite, // write handle
            &sa,      // security attributes
            0      // number of bytes reserved for pipe - 0 default
            );

    // Make child process use hPipeOutputWrite as standard out,
    // and make sure it does not show on screen.
    si.cb = sizeof(si);
    si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput   = hPipeInputRead;
    si.hStdOutput  = hPipeOutputWrite;
    si.hStdError   = hPipeOutputWrite;

    CreateProcess (
          NULL, "cmd.exe",
          NULL, NULL,
          TRUE, 0,
          NULL, NULL,
          &si, &pi);

    // Now that handles have been inherited, close it to be safe.
    // You don't want to read or write to them accidentally.
    CloseHandle(hPipeOutputWrite);
    CloseHandle(hPipeInputRead);

    // Now test to capture DOS application output by reading
    // hPipeOutputRead.  Could also write to DOS application
    // standard input by writing to hPipeInputWrite.
    sprintf(szMsg, "dir *.txt /b\nexit\n");
    WriteFile(
          hPipeInputWrite,      // handle of the write end of our pipe
          &szMsg,               // address of buffer that send data
          18,                   // number of bytes to write
          &dwNumberOfBytesWrite,// address of number of bytes read
          NULL                  // non-overlapped.
          );

    while(TRUE)
    {
       bTest=ReadFile(
          hPipeOutputRead,      // handle of the read end of our pipe
          &szBuffer,            // address of buffer that receives data
          256,                  // number of bytes to read
          &dwNumberOfBytesRead, // address of number of bytes read
          NULL                  // non-overlapped.
          );

      if (!bTest){
          sprintf(szMsg, "Error #%d reading pipe.",GetLastError());
          MessageBox(NULL, szMsg, "WinPipe", MB_OK);
          break;
      }

      // do something with data.
      szBuffer[dwNumberOfBytesRead] = 0;  // null terminate
      MessageBox(NULL, szBuffer, "WinPipe", MB_OK);
    }

    // Wait for CONSPAWN to finish.
    WaitForSingleObject (pi.hProcess, INFINITE);

    // Close all remaining handles
    CloseHandle (pi.hProcess);
    CloseHandle (hPipeOutputRead);
    CloseHandle (hPipeInputWrite);

    return 0;
}
kmsch 2016-01-13
  • 打赏
  • 举报
回复
引用 9 楼 zhao4zhong1 的回复:
#include <windows.h>
//This will clear the console.
void ClearConsole()
{
   //Get the handle to the current output buffer...
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   //This is used to reset the carat/cursor to the top left.
   COORD coord = {0, 0};
   //A return value... indicating how many chars were written
   //   not used but we need to capture this since it will be
   //   written anyway (passing NULL causes an access violation).
   DWORD count;
   //This is a structure containing all of the console info
   // it is used here to find the size of the console.
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   //Here we will set the current color
   if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
   {
      //This fills the buffer with a given character (in this case 32=space).
      FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      //This will set our cursor position for the next print statement.
      SetConsoleCursorPosition(hStdOut, coord);
   }
}
是因为system命令有什么副作用吗,用代码实现可以,但还有一些其他的system命令,有没办法解决
赵4老师 2016-01-13
  • 打赏
  • 举报
回复
#include <windows.h>
//This will clear the console.
void ClearConsole()
{
   //Get the handle to the current output buffer...
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   //This is used to reset the carat/cursor to the top left.
   COORD coord = {0, 0};
   //A return value... indicating how many chars were written
   //   not used but we need to capture this since it will be
   //   written anyway (passing NULL causes an access violation).
   DWORD count;
   //This is a structure containing all of the console info
   // it is used here to find the size of the console.
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   //Here we will set the current color
   if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
   {
      //This fills the buffer with a given character (in this case 32=space).
      FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
      //This will set our cursor position for the next print statement.
      SetConsoleCursorPosition(hStdOut, coord);
   }
}
ID870177103 2016-01-13
  • 打赏
  • 举报
回复
你调用system就行的时候先重定向到别的地方,完了再换回来
赵4老师 2016-01-13
  • 打赏
  • 举报
回复
使用命令重定向操作符可以使用重定向操作符将命令输入和输出数据流从默认位置重定 向到不同的位置。输入或输出数据流的位置即为句柄。 下表将列出可用的句柄。 句柄 句柄的数字代号 描述 STDIN 0 键盘输入 STDOUT 1 输出到命令提示符窗口 STDERR 2 错误输出到命令提示符窗口 UNDEFINED 3-9 这些句柄由应用程序单独定义,并且是各个工具特定的。 数字 0 到 9 代表前 10 个句柄。可以使用命令 Cmd.exe 运行程序并将该程序前 10 个 句柄中的任何一个重定向。要指定想使用的句柄,可在重定向操作符前面键入该句柄的 数字。如果未定义句柄,则默认的 < 重定向输入操作符是 0,而默认的 > 重定向输出 操作符是 1。键入 > 或 < 操作符之后,必须指定要读取或写入数据的位置。可以指定 文件名或另一个现有的句柄。 要指定重定向到现有句柄,请使用与 (&) 字符,后面接要重定向的句柄号 (例如 &句柄#)。例如,下面的命令可以将句柄 2(即 STDERR)重定向到 句柄 1(即 STDOUT): 2>&1 下表列出了可用于将输入和输出数据流进行重定向的操作符。 重定向操作符 描述 > 将命令输出写入到文件或设备(例如打印机)中,而不是写在命令提示符窗口或句柄中。 < 从文件中而不是从键盘或句柄中读入命令输入。 >> 将命令输出添加到文件末尾而不删除文件中的信息。 >& 将一个句柄的输出写入到另一个句柄的输入中。 <& 从一个句柄读取输入并将其写入到另一个句柄输出中。 | 从一个命令中读取输出并将其写入另一个命令的输入中。也称作管道。 默认情况下,可以从键盘将命令输入(即 STDIN 句柄)发送到 Cmd.exe,然后由 Cmd.exe 将命令输出(即 STDOUT 句柄)发送到命令提示符窗口。 重定向输入 (<) 要将键盘输入重定向到文件或设备,请使用 < 操作符。例如,要从 File.txt 获取 sort 命令的输入,请键入: sort<file.txt File.txt 的内容将以字母顺序列表的方式显示在命令提示符窗口中。 < 操作符可以打开具有只读访问的指定文件名。所以,不能使用该操作符向文件中写入 信息。例如,如果以 <&2 启动程序,则所有试图读取句柄 0 的操作都将失败,因为句 柄 2 最初是以只写访问打开的。 注意 0 是 < 重定向输入操作符的默认句柄。 重定向输出 (>) 几乎所有的命令都将输出发送到命令提示符窗口。即使将输出发送到驱动器或打印机的 命令也会在命令提示符窗口显示消息和提示。 要将输出从命令提示符窗口重定向到文件或设备,请使用 > 操作符。可以在许多命令中 使用该操作符。例如,要将 dir 输出重定向到 Dirlist.txt,请键入: dir>dirlist.txt 如果 Dirlist.txt 不存在,Cmd.exe 将创建该文件。如果 Dirlist.txt 存在,Cmd.exe 将使用 dir 命令的输出替换文件中的信息。 要运行 netsh routing dump 命令,然后将输出发送到 Route.cfg,请键入: netsh routing dump>c:\route.cfg > 操作符可以打开具有只写访问属性的指定文件。所以,不能使用该操作符读取文件。 例如,如果使用重定向 >&0 启动程序,则所有试图写入句柄 1 的操作都将失败,因为 句柄 0 最初是以只读访问打开的。 注意 1 是 > 重定向输出操作符的默认句柄。 复制句柄 重定向操作符 & 可以将输出或输入从一个指定句柄复制到另一个指定的句柄。例如, 要将 dir 输出发送到 File.txt 并将错误输出发送到 File.txt,请键入: dir>c:\file.txt 2>&1 复制句柄时,可以复制该句柄原状态的所有特性。例如,如果一个句柄具有只写访问的 属性,则该句柄的所有副本都具有只写访问属性。不能将一个具有只读访问属性的句柄 复制到另一个具有只写访问属性的句柄。 使用 & 操作符重定向输入和副本 要将重定向输入操作符 (<) 与复制操作符 (&) 一起使用,指定的文件必须已经存在。 如果输入文件存在,Cmd.exe 将以只读方式打开该文件,然后将文件中包含的字符作为 输入发送到此命令(如同从键盘输入一样)。如果指定了句柄,Cmd.exe 将指定的句柄 复制到系统现有的句柄中。 例如,要以句柄 0 输入读取(即 STDIN)的方式打开 File.txt,请键入: <file.txt 要打开 File.txt,并在内容排序后将输出发送到命令提示符窗口(即 STDOUT),请键入: sort<file.txt 要查找 File.txt,然后将句柄 1(即 STDOUT)和句柄 2(即 STDERR)重定向到 Search.txt,请键入: findfile file.txt>search.txt 2<&1 要以句柄 0 输入读取(即 STDIN)的方式复制用户定义句柄 3,请键入: <&3 使用 & 操作符重定向输出和复制 如果将输出重定向到文件且指定了现有的文件名,Cmd.exe 将以只写方式打开文件并覆 盖该文件内容。如果指定了句柄,Cmd.exe 将文件复制到现有句柄中。 要将用户定义句柄 3 复制到句柄 1,请键入: >&3 要将包括句柄 2(即 STDERR)的所有输出从 ipconfig 命令重定向到 句柄 1(即 STDOUT),然后将输出重定向到 Output.log,请键入: ipconfig.exe>>output.log 2>&1 使用 >> 重定向操作符追加输出 要从命令中将输出添加到文件末尾而不丢失文件中已存在的任何信息,请使用两个连续 的大于号(即 >>)。例如,下面的命令可以将由 dir 命令生成的目录列表追加到 Dirlist.txt 文件: dir>>dirlist.txt 要将 netstat 命令的输出追加到 Tcpinfo.txt 的末尾,请键入: netstat>>tcpinfo.txt 使用管道操作符 (|) 管道操作符 (|) 可以提取一个命令的输出(默认情况下是 STDOUT),然后将其导入另 一个命令的输入中(默认情况下是 STDIN)。例如,下面的命令将对目录分类: dir | sort 在本例中,将同时启动两个命令,但随后 sort 命令会暂停,直到它接收到 dir 命令 的输出为止。sort 命令使用 dir 命令的输出作为输入,然后将输出发送到 句柄 1(即 STDOUT)。 合并带重定向操作符的命令 可以通过合并带有其他命令和文件名的筛选器命令创建自定义命令。例如,可以使用以 下命令存储包含“LOG”字符串的文件名: dir /b | find "LOG" > loglist.txt dir 命令的输出通过 find 筛选器命令发送。包含字符串 "LOG" 的文件名作为文件名 列表(例如,NetshConfig.log、Logdat.svd 和 Mylog.bat)存储在文件 Loglist.txt 中。 要在相同命令中使用多个筛选器,请使用管道 (|) 分隔筛选器。例如,下面的命令将 搜索 C 盘上的每个目录以查找包含 "LOG" 字符串的文件名,并且在命令提示符窗口中 每次显示一屏: dir c:\ /s /b | find "LOG" | more 利用管道 (|) 可以将 Cmd.exe 导向为通过 find 筛选器命令发送 dir 命令输出。 find 命令只选择包含字符串 "LOG" 的文件名。more 命令可以显示由 find 命令选择 的文件名(在命令提示符窗口中每次显示一屏)。有关筛选器命令的详细信息,请参阅 使用筛选器。
kmsch 2016-01-13
  • 打赏
  • 举报
回复
引用 13 楼 zhao4zhong1 的回复:
#include<stdio.h>
int main() {
    printf("11\n22\n33\n");
    return 0;
}
在cmd窗口中,输入以下命令将程序的输出重定向到文件c:\123.txt中: cd /d 你的.exe程序所在盘符和文件夹 你的.exe程序 >c:\123.txt
怎么重定向回来
赵4老师 2016-01-13
  • 打赏
  • 举报
回复
#include<stdio.h>
int main() {
    printf("11\n22\n33\n");
    return 0;
}
在cmd窗口中,输入以下命令将程序的输出重定向到文件c:\123.txt中: cd /d 你的.exe程序所在盘符和文件夹 你的.exe程序 >c:\123.txt
kmsch 2016-01-13
  • 打赏
  • 举报
回复
引用 11 楼 zhao4zhong1 的回复:
一般重定向使用命令行管道操作实现。
也就是说?希望赵4老师点一下
赵4老师 2016-01-13
  • 打赏
  • 举报
回复
一般重定向使用命令行管道操作实现。
kmsch 2016-01-12
  • 打赏
  • 举报
回复
引用 3 楼 ID870177103 的回复:
freopen是过时不推荐的函数,使用别的方式代替
由于是别人写的代码,输出到控制台,我想改成输出到文件,他是用printf,如果不这样,我要改的太多了
kmsch 2016-01-12
  • 打赏
  • 举报
回复
引用 2 楼 pineapple_kurokumo 的回复:
[quote=引用 1 楼 pineapple_kurokumo 的回复:] 头文件难道不应该是这个#include<stdlib.h>?
我记得好像是清屏用的啊。。。[/quote] 是的,加上这个头文件
ID870177103 2016-01-12
  • 打赏
  • 举报
回复
freopen是过时不推荐的函数,使用别的方式代替
pineapple_kurokumo 2016-01-12
  • 打赏
  • 举报
回复
引用 1 楼 pineapple_kurokumo 的回复:
头文件难道不应该是这个#include<stdlib.h>?
我记得好像是清屏用的啊。。。
pineapple_kurokumo 2016-01-12
  • 打赏
  • 举报
回复
头文件难道不应该是这个#include<stdlib.h>?
数据结构 课程设计 void main() { list *head=NULL;//头指针初始化 FILE *fp;//定义文件指针 int m;//功能代号吗 do{ printf("\n #############################请选择################################\n"); printf(" # 1、信息输入 "); printf(" 2、显示信息 #\n"); printf(" # 3、查找姓名 "); printf(" 4、删除信息 #\n"); printf(" # 5、修改信息 "); printf(" 6、打开通讯录 #\n"); printf(" # 7、添加信息 "); printf(" 8、 保存 #\n"); printf(" # 9、清屏 "); printf(" 0、退出 #"); printf("\n ###################################################################\n"); printf(" 提示:信息输入和添加信息时最好存入字符,否则,在打开存储文件时,可能会出现乱码!\n"); printf("==输入要执行的功能代号:_"); scanf("%d",&m); switch(m) { case 1:enter(head);break; case 2:display(head); break; case 3:search(head); break; case 4:delete_name(head);break; case 5:change(head);break; case 6:load(head);break; case 7:insert(head);break; case 8:save(head,fp);printf("==保存成功==\n");break; case 9:system("cls");break; } } while(m!=0); } 2、信息输入: void enter(list *&head) { list *p0,*p1,*p2;//定义指针 int m;//作为判断是否继续新建的条件 FILE *fp; p0=(list *)malloc(LEN); //开辟一个新单元 p0->next=NULL;//结点指针域为空 head=p0;//第一个结点,即为头结点 printf("请输入信息建立通讯录:\n"); getchar(); scanfdata(p0);//输入数据 p2=p0; printf("是否继续按1输入,按0结束_"); scanf("%d",&m); while(m) { getchar(); p1=(list *)malloc(LEN); //开辟一个新单元 p1->next=NULL; p2->next=p1; scanfdata(p1);//输入数据 p2=p1; head->n = head->n+1;//表长 printf("是否继续按1输入,按0结束_"); scanf("%d",&m); } if(m==0) { save(head,fp);//把信息存到相应文件 } } 3、显示信息 void display(list *head) { list *p; //定义移动指针 int i; char *menu[]={"姓名","城市","电话", "QQ"}; p=head; printf("--------------------------------------------------------------------\n"); for(i=0;i<4;i++) printf("%-20s",menu[i]); printf("\n"); if (head!=N

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧