getchar()的一点思考

本文深入探讨了编程中使用 getchar() 函数时,输入字符 'a' 后回车( )也被视为一次输入的原理。通过编写验证程序,展示了回车作为输入的一部分,并解释了其在程序执行中的作用。

【熊猫大叔   转载请注明出处:http://blog.youkuaiyun.com/pandaflyup

今天看书看到一道题:验证表达式getchar()!=EOF的值是0还是1。
于是乎我就编写了下面一段程序:
int main()
{
int c;
while(c=getchar()!=EOF)//!=优先级大于=,验证后边式子的返回值 
printf("不等于EOF时返回值:%d\n",c);
printf("等于EOF时返回值:%d\n",c);
system("PAUSE");
return 0;
} 
输入字符‘a’回车,结果打印了两行,也就是循环执行了两次。

当时一愣,想着我输入一个字符,不就该打印一行(执行一次吗),怎么执行了两次,后来经过仔细推敲
加用别的程序验证,发现回车(\n)也被当成了一次输入,我平常都以为回车只表示字符输入的结束,其实
真相是回车也是一次输入,只不过是放在缓存中,当执行完第一个动作(输入的a)再执行换行。

下面给出验证程序:
int main()
{
long nc=0;
int c;
while((c=getchar())!=EOF)
{
            putchar(c);
   nc++;
         }
printf("the length is %d",nc);
system("PAUSE");
return 0;
} 
输入字符‘a’,回车表示字符输入结束,执行循环体,再ctrl+z(EOF)退出循环,此时打印出的长度是2,
说明回车也算成了一次输入。

可能大家早已知道这个细节,只是我平常没有细细推敲导致对问题一知半解,甚至根本不理解。所以再简单
的程序也经不起推敲,还是有很多东西可以学。

// 实验一创建进程.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <iostream> #include <stdio.h> //创建子进程,与父进程执行相同的程序。 void StartClone(int nCloneID) { // 获取当前进程的可执行文件名。 TCHAR szFilename[MAX_PATH] ; :: GetModuleFileName( NULL, //一个模块的句柄。模块句柄跟一般的句柄不一样, //模块句柄指向的就是EXE和DLL等在虚拟地址空间的位置。 //如果该参数为NULL,该函数返回该应用程序全路径。 szFilename, MAX_PATH) ; // 格式化用于创建新进程的命令行,包括EXE文件名和克隆ID TCHAR szCmdLine[MAX_PATH]; :: sprintf(szCmdLine,"\"%s\"%d",szFilename,nCloneID); // 用于新进程的STARTUPINFO结构 STARTUPINFO si; :: ZeroMemory(reinterpret_cast <void*> (&si) , sizeof(si) ) ; si.cb = sizeof(si) ; // 必须是本结构的大小 // 返回的用于新进程的进程信息 PROCESS_INFORMATION pi; // 使用同一可执行文件和带有克隆ID的命令行创建新进程。 BOOL bCreateOK=::CreateProcess( szFilename, // 新进程的可执行文件名 szCmdLine, // 传给新进程的命令行参数 NULL, // 缺省的进程安全性 NULL, // 缺省的线程安全性 FALSE, // 不继承句柄 CREATE_NEW_CONSOLE, // 使用新的控制台 NULL, // 新的环境 NULL, // 当前目录 &si, // 启动信息 &pi) ; // 返回的进程信息 //不使用的句柄最好关掉 if (bCreateOK) { :: CloseHandle(pi.hProcess) ; :: CloseHandle(pi.hThread) ; } } int main(int argc, char* argv[] ) { // 进程的克隆ID int nClone(0) ; //第一个进程argc为1,以后每个进程命令行有两个参数, //其中第二个是克隆ID。 if (argc > 1) { // 从第二个参数中提取克隆ID :: sscanf(argv[1] , "%d" , &nClone) ; } // 显示进程的克隆ID std :: cout << "Process ID:" << :: GetCurrentProcessId() << ", Clone ID:" << nClone << std :: endl; // 创建新进程,其nClone为1-8 const int c_nCloneMax=8; if (nClone < c_nCloneMax) { :: Sleep(1000) ; StartClone(nClone+1) ; } // 等待输入一个字符,以便观察。输入一个字符后,程序结束。 std::cout<<"input a char:"; getchar(); std::cout<<"I'm stopped ... Bye-Bye"; return 0; } /* 思考题: 1.main函数的两个参数如何使用? 2.main函数是如何运行起来的? 3.运行后在系统任务管理器中查看所创建进程映像名是否相同? 4.父子进程运行同一可执行文件,如何能够区分出他们? 5.不同进程的克隆ID是如何获取到的? 6.如果在克隆ID为0的进程中创建克隆ID为1-8的进程,应该如何修改程序? */
最新发布
11-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值