C语言读取磁盘分区信息(MBR、DPT、EBR)

article/2025/8/27 12:43:37

文章目录

  • 简介
  • 使用的函数
    • 1.CreateFile()函数打开设备
    • 2.DeviceIoControl()函数返回磁盘设备信息
    • 3.SetFilePointer()函数设置读取磁盘信息位置
    • 4.ReadFile()函数读取磁盘内容
  • 源代码
  • 结果分析
      • MBR部分:
      • 第一个EBR的DPT内容为:
      • 第2个EBR内容
  • 总结

简介

  在win8以后,磁盘格式一般是GPT格式的,做实验是在winXP虚拟机上完成的,partition style是MBR。在虚拟机上分配了40GB的硬盘空间。三个主分区盘C、E、F,一个扩展分区里面有三个逻辑盘G、H、I。
在这里插入图片描述

使用的函数

1.CreateFile()函数打开设备

HANDLE CreateFile(
  LPCSTR lpFileName,
   DWORD dwDesiredAccess,
   DWORD dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD dwCreationDisposition,
  DWORD dwFlagsAndAttributes,
  HANDLE hTemplateFile
);

  • 第1个参数lpFileName为要创建或打开的文件或设备的名称。磁盘为TEXT("\\.\PhysicalDrive0"),如果有两个盘,第2个为1。
  • 第2个参数dwDesiredAccess为请求访问文件或设备,常取值为GENERIC_READ, GENERIC_WRITE或两者(GENERIC_READ | GENERIC_WRITE)
  • 第3个参数为dwShareMode,是请求的文件或设备共享模式,可以是读取,写入,两者,删除
  • 第4个参数为lpSecurityAttributes,是指向SECURITY_ATTRIBUTES 结构的指针,如果此参数为NULL,则CreateFile返回的句柄不能由应用程序可能创建的任何子进程继承,使用默认安全属性。
  • 第5个参数dwCreationDisposition,对存在或不存在的文件或设备执行的操作。对于文件以外的设备,此参数通常设置为OPEN_EXISTING。
  • 第6个参数为dwFlagsAndAttributes,是文件或设备属性和标志。
  • 第7个参数为hTemplateFile,具有GENERIC_READ访问权限的模板文件的有效句柄。此参数可以为NULL。
  • 返回值:如果函数成功,则返回值是指定文件,设备,命名管道或邮件槽的打开句柄。如果函数失败,则返回值为INVALID_HANDLE_VALUE。获取错误码,可以调用GetLastError()函数。

2.DeviceIoControl()函数返回磁盘设备信息

BOOL DeviceIoControl(
  HANDLE hDevice,
  DWORD dwIoControlCode,
  LPVOID lpInBuffer,
  DWORD nInBufferSize,
  LPVOID lpOutBuffer,
  DWORD nOutBufferSize,
  LPDWORD lpBytesReturned,
  LPOVERLAPPED lpOverlapped
);

  • 第1个参数为hDevice,是要对其执行操作的设备的句柄,本实验中是CreateFile()函数的返回的设备句柄。
  • 第2个参数dwIoControlCode,是操作的控制代码,该值标识要执行的特定操作以及执行它的设备类型。使用IOCTL_DISK_GET_DRIVE_GEOMETRY,用于获取磁盘信息。
  • 第3个参数为lpInBuffer,是指向输入缓冲区的指针,可以为NULL。
  • 第4个参数为nInBufferSize,是输入缓冲区大小,以字节为单位。
  • 第5个参数为lpOutBuffer,指向输出缓冲区的指针,用于接收操作返回的数据。
  • 第6个参数为nOutBufferSize,是输出缓冲区的大小,以字节为单位。
  • 第7个参数为lpBytesReturned,是一个指向变量的指针,该变量接收存储在输出缓冲区中的数据大小(以字节为单位)。如果输出缓冲区太小而无法接收任何数据,则调用失败, GetLastError()返回 ERROR_INSUFFICIENT_BUFFER,并且lpBytesReturned为零。
  • 第8个参数为lpOverlapped,指向OVERLAPPED结构的指针。如果在未指定FILE_FLAG_OVERLAPPED的情况下打开 hDevice,则忽略lpOverlapped。
  • 返回值:如果操作成功完成,则返回值为非零值。

3.SetFilePointer()函数设置读取磁盘信息位置

DWORD SetFilePointer(
HANDLE hFile,
LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod
);

  • 第1个参数hFile是文件的句柄。
  • 第2个参数为lDistanceToMove,是表示距离的有符号数的低32位,用来指定文件指针的字节偏移。
  • 第3个参数lpDistanceToMoveHigh,是距离的高32位。
  • 第4个参数dwMoveMethod是文件指针移动的起点。

4.ReadFile()函数读取磁盘内容

BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);

  • 第1个参数hFile,是文件/设备句柄。
  • 第2个参数lpBuffer,是指向缓冲区的指针,用于接收读取的数据。
  • 第3个参数nNumberOfBytesToRead,是要读取的最大字节数。
  • 第4个参数lpNumberOfBytesRead,用于接收读取的字节数。
  • 第5个参数lpOverlapped可以为NULL。

源代码

#include <windows.h>
#include <winioctl.h> //DDK驱动开发与控制
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#define BufferLength 1024//将四个连续字节存放的值转为int型
uint32_t transtoint(unsigned char a[])
{uint32_t sum = 0UL;uint32_t temp = 0UL;for (int i = 3; i>=0; i--){temp = a[i];//先赋值				temp = temp <<( 8 * (3-i));		sum = sum | temp;}return sum;
}
//十六进制输出
bool HexOutput(char* buf, size_t len,bool ismbr, ULONGLONG * baseaddr,ULONGLONG * nextaddr,int EBRnum)
{bool mbrflag=1;//在读取MBR的时候判断条目是主分区还是扩展分区条目 unsigned char a = buf[0];if(ismbr)printf("-----------------------------------------------------");elseprintf("--------------------------第%d个EBR------------------",EBRnum);//printf("第一字节是:%x\n\n", a);if(ismbr)printf("          第一部分(MBR):\n\n");elseprintf("          第一部分(EBR):\n\n");int flag = 0;for (size_t i = 0; i < len; ++i){unsigned char c = buf[i]; // must use unsigned char to print >128 value flag++;if (c < 16)printf("0%x ", c);elseprintf("%x ", c);if (i == 445){flag = 0;printf("\n\n          第二部分(分区表):\n");}if (i == 509){flag = 0;printf("\n\n          第三部分(结束标志):\n");}if ((flag) % 16 == 0)printf("\n");}printf("\n<-------------------分区表信息解析------------------->\n\n");printf("\n\n分区地址和大小分别为: \n\n");	int limit=ismbr?509:477;//如果已经知道是扩展分区的EBR,不用读取那么多,rank=1是分区表,rank=2是指向下一个的for (int m = 445, rank = 1; m < limit&&rank<=4; m += 16, rank++){unsigned char fifth = buf[m + 5];//取得第五位文件系统标志位,十六进制为05H或者0FH是扩展分区 		if(fifth==0x5||fifth==0xf)//是扩展分区条目,不用往后读了 {printf("This is an extend patition!\n");mbrflag=0;	rank = 4;}//不是mbr是扩展分区EBR if (fifth < 16) //调整输出格式printf("第%d分区表标志位为: 0%x\n", rank, fifth);elseprintf("第%d分区表标志位为: %x\n", rank, fifth);if (fifth == 0x00)//当第五位(标志位)是00时,代表分区表信息为空,无分区{printf(" 分区表为空\n\n");//也不用往后读了 }else {//分区项 unsigned char offsetadd[4] = { 0 };//倒着读,高字节在高地址处for (int n = m + 12, t = 0; n > m + 8, t < 4; n--, t++){unsigned char temp = buf[n];if (temp < 16)printf("  0%x  ", temp);elseprintf("  %x  ", temp);offsetadd[t] = buf[n];}//计算地址,转换为十进制扇区数LBAprintf("\n");uint32_t tempadd = transtoint(offsetadd);printf("\n开始地址为: %I64x", (ULONGLONG)tempadd * (ULONGLONG)512 + *baseaddr);if(ismbr&&!mbrflag)// if in mbr and got a extend entry,the EBR at relsecor+nowbase(0){*baseaddr=(ULONGLONG)tempadd* (ULONGLONG)512 + *baseaddr;//only change once*nextaddr = (ULONGLONG)0UL;}				else if (!mbrflag)//if it's the extend entry{*nextaddr = (ULONGLONG)tempadd * (ULONGLONG)512;}printf("\n\n");printf("大小:");for (int p = m + 16, w = 0; p > m + 12, w < 4; p--, w++){unsigned char temp1 = buf[p];if (temp1 < 16)printf("  0%x  ", temp1);elseprintf("  %x  ", temp1);offsetadd[w] = buf[p];}//计算大小,转化为GB单位printf("\n");uint32_t tempsize = transtoint(offsetadd);if(ismbr && !mbrflag)printf("\n扩展盘总大小为: %lu 扇区 = %lf GB \n", tempsize, ((double)tempsize / 2.0 / 1024.0 / 1024.0));else if(!ismbr){printf("\n第%d逻辑盘大小为: %lu 扇区 = %lf GB \n",EBRnum, tempsize, ((double)tempsize / 2.0 / 1024.0 / 1024.0));}elseprintf("\n该盘大小为: %lu 扇区 = %lf GB \n", tempsize, ((double)tempsize / 2.0 / 1024.0 / 1024.0));}}printf("\n\n");return (mbrflag);
}//函数:对主分区表进行解析,分别得到每个分区的偏移地址以及分区大小
BOOL GetDriveGeometry(DISK_GEOMETRY *pdg, int addr)
{HANDLE hDevice;               // 设备句柄BOOL bResult;                 // results flagDWORD junk;                   // discard resultsccchar lpBuffer[BufferLength] = { 0 };//通过CreateFile来获得设备的句柄hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive0"), // 设备名称,这里指第一块硬盘GENERIC_READ,                // no access to the driveFILE_SHARE_READ | FILE_SHARE_WRITE,  // share modeNULL,             // default security attributesOPEN_EXISTING,    // disposition0,                // file attributesNULL);            // do not copy file attributesif (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive{printf("Creatfile error!May be no permission!ERROR_ACCESS_DENIED!\n");return (FALSE);}//通过DeviceIoControl函数与设备进行IObResult = DeviceIoControl(hDevice, // 设备的句柄IOCTL_DISK_GET_DRIVE_GEOMETRY, // 控制码,指明设备的类型NULL, 0, // no input bufferpdg,sizeof(*pdg),     &junk,                 // # bytes returned(LPOVERLAPPED)NULL); // synchronous I/OLARGE_INTEGER offset;//long long signedoffset.QuadPart = (ULONGLONG)addr * (ULONGLONG)512;//0SetFilePointer(hDevice, offset.LowPart, &offset.HighPart, FILE_BEGIN);//从0开始读MBRif(GetLastError())printf("错误类型代号:%ld\n\n", GetLastError());//如果出错了DWORD dwCB;//从这个位置开始读 BOOL bRet = ReadFile(hDevice, lpBuffer, 512, &dwCB, NULL);//如果不是MBR,bool finished=0; int EBRnum=0;ULONGLONG *baseaddr=new ULONGLONG,*nextaddr= new ULONGLONG;//扩展分区起始地址,EBR地址 *baseaddr = (ULONGLONG)0;*nextaddr = (ULONGLONG)0;finished=HexOutput(lpBuffer, 512,true,baseaddr,nextaddr,EBRnum);//先是读取MBRif(finished)CloseHandle(hDevice);else{//继续读do{EBRnum++;memset(lpBuffer, 0, sizeof(lpBuffer));offset.QuadPart = (ULONGLONG)(*baseaddr + *nextaddr);//find the EBRSetFilePointer(hDevice, offset.LowPart, &offset.HighPart, FILE_BEGIN);//读EBRif(GetLastError())printf("错误类型代号:%ld\n\n", GetLastError());//如果出错了ReadFile(hDevice, lpBuffer, 512, &dwCB, NULL);}while(!HexOutput(lpBuffer, 512,false,baseaddr,nextaddr,EBRnum));CloseHandle(hDevice);}delete baseaddr;delete nextaddr;return bResult;
}
extern int add[20];
extern int disknum;
int main()
{DISK_GEOMETRY pdg;            // 保存磁盘参数的结构体BOOL bResult;                 // generic results flagULONGLONG DiskSize;           // size of the drive, in bytesprintf("<-----------------欢迎使用分区读取程序----------------->\n\n");bResult = GetDriveGeometry(&pdg, 0);if (bResult){DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *(ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;printf("磁盘总大小 = %I64d (Bytes) = %I64d (Gb)\n", DiskSize, DiskSize / (1024 * 1024 * 1024));}else{printf("GetDriveGeometry failed. Error %ld.\n", GetLastError());}return ((int)bResult);
}

结果分析

运行程序解析磁盘信息的结果,与使用Winhex查看计算是一致的。

MBR部分:

在这里插入图片描述

分区地址和大小分别为:

第1分区表标志位为: 07
00 00 00 3f
开始地址为: 7e00
大小: 02 7f 8c b2
该盘大小为: 41913522 扇区 = 19.985925 GB

第2分区表标志位为: 07
02 7f 8c f1
开始地址为: 4ff19e200
大小: 00 3f fa c5
该盘大小为: 4192965 扇区 = 1.999362 GB

第3分区表标志位为: 07
02 bf 87 b6
开始地址为: 57f0f6c00
大小: 00 3f fa c5
该盘大小为: 4192965 扇区 = 1.999362 GB

This is an extend patition!
第4分区表标志位为: 0f
02 ff 82 7b
开始地址为: 5ff04f600
大小: 02 00 53 aa
扩展盘总大小为: 33575850 扇区 = 16.010213 GB

查看C盘信息,开始地址7E00,20G:
在这里插入图片描述
查看E盘信息,开始抵制4FF19E200,大小2G:
在这里插入图片描述
查看F盘信息,开始地址57F0F6C00,大小2G:
在这里插入图片描述
查看第4个DPT对应的扩展分区的EBR,扩展分区的EBR所在地址位5FF04F600:
在这里插入图片描述

第一个EBR的DPT内容为:

在这里插入图片描述
  第一个条目地址信息中3F 00 00 00是63,指向第一个逻辑盘。计算这个逻辑盘开始地址为63*512=7E00H,加上5FF04F600H得到5FF057400H,这就是G盘的起始位置。G盘的大小信息为0E 12 A0 00,也就是10490382个扇区,10490382*512/1024/1024/1024=5GB。
在这里插入图片描述
  第2个条目是第5个字节内容是05H,表示是扩展分区。(之前MBR中的第4个扇区第5字节是0FH,也表示这是一个扩展分区)。扩展分区的地址信息为A0124DH,也就是相对于扩展分区开始位置5FF04F600H起的第10490445个扇区(换成字节是140249A00H)处存放着下一个扩展分区的MBR。这个位置是140249A00H+5FF04F600H =73F299000H。在这个位置,的确放着下一逻辑盘,也就是H盘的EBR。用同样方式可以计算。
 在这里插入图片描述

第1分区表标志位为: 07
00 00 00 3f
开始地址为: 5ff057400
大小: 00 a0 12 0e
第1逻辑盘大小为: 10490382 扇区 = 5.002204 GB

This is an extend patition!
第2分区表标志位为: 05
00 a0 12 4d
开始地址为: 73f299000
大小: 00 a0 12 4d
第1逻辑盘大小为: 10490445 扇区 = 5.002234 GB

第2个EBR内容

在这里插入图片描述

分区地址和大小分别为:
第1分区表标志位为: 07
00 00 00 3f
开始地址为: 5ff057400
大小: 00 a0 12 0e
第2逻辑盘大小为: 10490382 扇区 = 5.002204 GB

This is an extend patition!
第2分区表标志位为: 05
01 40 24 9a
开始地址为: 87f4e2a00
大小: 00 c0 2f 10
第2逻辑盘大小为: 12594960 扇区 = 6.005745 GB

总结

  MBR的四个分区表的组合有两种:全部是主分区;三个主分区+一个扩展分区。在阅读分区表条目的时候,(从第1字节开始)第5字节中存放的信息也比较重要,如果是05H或者是0FH,表示这是一个扩展分区条目,地址信息指向的是EBR,否则如果不是0,就是一个主分区条目,指向的是每个主分区的开始扇区。如果是在EBR中,在扩展分区表部分,只有前两个条目有效,最后两个是全为0的没有用到,第1个条目指向了目前已经发现了的逻辑盘,第2个条目如果不是全0,说明还有下一个逻辑盘,指向的就是下一个EBR。
  地址信息Relative在主分区中,是0。在扩展分区中,是主扩展分区的开始位置所在扇区,可以从MBR中获取到。而Sectors指的是分区占的总扇区数,在MBR中,第4个如果是扩展分区的话,表示是整个扩展分区里面所有逻辑盘的大小。
  自己电脑的分区逻辑图如图所示:
在这里插入图片描述


PS:程序写的时候有的显示BUG这种就没有改了。。。。。


http://chatgpt.dhexx.cn/article/URN6r6Ik.shtml

相关文章

使用Epoch-Based Reclamation(EBR,特定域回收的一种方法)修改 lazy-list

如前文所说&#xff0c;lazy-list最大的隐患莫过于逻辑删除&#xff0c;而没有物理删除问题&#xff0c;因此EBR首先就把这个问题给他solve了。 一.EBR修改部分 int parse_delete(intset_l_t *set, val_t val) {node_l_t *pred, *curr;int result, validated, isVal;while(1)…

淘宝电商搜索EBR算法笔记

淘宝电商搜索EBR算法笔记 - 知乎《Embedding-based Product Retrieval in Taobao Search》介绍了淘宝目前最新的EBR算法。仍然是一个双塔的结构&#xff0c;query/user一个塔&#xff0c;item一个塔&#xff0c;各自得到向量表示&#xff0c;然后计算内积。 网络结构如上图所示…

解决西门子ebr设备模块更新报错,EQP_STATEVALUE more than one row

问题排查报告 原文来至 问题跟踪 首先定位到EQP_STATEVALUE表&#xff0c;发现数据出现重复&#xff1a; 执行语句取出所有非重复数据&#xff1a; select t.stateid,t.fk_statelistcst,t.code,t.label,t.functionid,t.pk_id,t.dlu,t.dluunit,t.cpt,t.haseqpimpact from EQP…

机械臂关节模组制动相关(零差云控eBr)

目录 前言一、电磁插销式抱闸1.原理2.特点 二、电磁摩擦片式制动器1.原理2.特点 三、零差云控电磁摩擦片式制动器&#xff08;eBreaker&#xff09;1.简介2.使用说明需要注意的事情3.接线 总结参考文献 前言 现阶段机械臂的制动方法主要有两种&#xff0c;一种是电磁插销式抱闸…

西门子EBR与BATCH通讯方法,mes与batch交互

最新更新请访问&#xff1a;mesebr.com 链接 1 前期准备 1.1 网络检查 两台服务器防火墙全部关闭&#xff1b;两台服务器之间可以相互ping同&#xff0c;若batch服务器连接oracle数据库的连接名称写的机器名&#xff0c;则batch服务器ping机器名也要可以ping通&#xff1b; 1…

WinHex数据恢复笔记-数据恢复与硬件维护-MBR格式--MBR,EBR系统结构

MBR&#xff0c;EBR系统结构 MBR限制2TB&#xff0c;最多有4个逻辑分区—如果有扩展&#xff08;3个主分区和1个扩展分区&#xff09; FAT32不能在大于32GB的盘上添加 MBR指向第一个EBR 第一个EBR(以链表)指向第二个EBR(以链表)指向第二个EBR(以链表)… MBR MBR数据结构 4…

西门子MES软件ebr脚本使用说明-SIMATIC IT EBR(Opcenter Execution Pharma

最新更新发布在此处 ebr脚本常用函数 ###参数输入输出 输入的type选择tag value;输出的type选择tag NAME; 实例 mData.InsertData ousNAME,0,straaa 输出文本 mData.InsertData ousAGE,1,age 输出数字html直接输出 mRecordText.WriteHTML str_htmlr 可直接输出html内…

每周一文(六)Facebook EBR向量召回模型

契机 从样本和模型两方面来介绍向量级别召回模型的由来。提出很有建设性的工业级别的参考价值。 样本角度 有监督的二分类模型需要构建正负样本&#xff0c;正样本的选择不管是召回和排序来说都是一致的&#xff0c;即用户有显式的点击行为的样本为正样本。而对于召回模型(甚…

主引导记录(MBR)、硬盘分区表(DPT)、扩展引导记录(EBR)

前言 最近在研究使用grub引导自制操作系统时&#xff0c;发现grub链式引导过程中向boot传递的硬盘分区表表项数据有疑问&#xff0c;特此记录下。 一、主引导记录&#xff08;MBR&#xff09; MBR是存储在计算机硬盘的第一个物理扇区的512字节的数据块&#xff0c;它包含了引…

MES管理端介绍,ebr二次开发产品—SIMATIC IT EBR(Opcenter Execution Pharma)

原文来至&#xff1a;访问原文 西门子MES软件ebr功能很强大&#xff0c;但给用户若只想查看一些数据是非常不方便&#xff0c;对外接口提供的文档也不具体&#xff0c;所以我二次开发了EBR的管理端。 主要功能 权限管理物料管理工单管理族谱批记录查看报表与看板审计追踪记录 …

NTFS文件系统详解(二)MBR\EBR基本信息

NTFS文件系统详解&#xff08;二&#xff09;MBR\EBR基本信息 一、MBR结构分析1. 第一个分区表项2. 第二个分区表项3. 第三个分区表项4. 第四个分区表项 二、EBR结构分析1. 第一个分区表项2. 第二个分区表项2.1 第一个分区表项2.2 第二个分区表项2.3 第三个分区表项 NTFS文件系…

MBR、EBR与DBR详解

demo&#xff1a;https://github.com/Hilaver/NtfsResolution/ 先看一张硬盘图片&#xff08;一个盘面&#xff09;&#xff1a; MBR 主引导记录&#xff08;MBR&#xff0c;Main Boot Record&#xff09;是位于磁盘最前边的一段引导&#xff08;Loader&#xff09;代码。它负…

MBR、EBR、DBR是什么

通常情况下可以这样描述这几个概念&#xff1a; MBR&#xff1a;为计算机启动后从可启动介质上首先装入内存并且执行的代码&#xff0c;通常用来解释分区结构。以硬盘为例&#xff0c;通常为LBA的0扇区。 EBR:自MICROSOFT推出扩展分区的概念后&#xff0c;扩展分区就沿用了基本…

NTFS文件系统详解(二)之MBR(EBR)基本信息

经过上一篇文章对硬盘的基本结构的详细介绍后,我们再来看看MBR和EBR的结构 MBR(Main Boot Record 主引导记录区)位于整个硬盘的0磁道0柱面1扇区。不过,在总共512字节的主引导扇区中,MBR只占用了其中的446个字节,另外的64个字节交给了 DPT(Disk Partition Table硬盘分区表…

EBR内容解析

原先博客放弃使用,几篇文章搬运过来 EBR(Extended Boot Record)即扩展分区引导记录.类似于主引导记录MBR.因为MBR的四条分区信息的限制,可以使用EBR方便扩展. 它的结构与MBR类似于,但是没有引导程序和磁盘签名,仅仅保留了分区表和结束标志. 下面以实例分析: 新建一个512MB虚拟…

C++中常见的几种输入字符串的方法

C中常见的几种输入字符串的方法_是赵薰薰呀的博客-CSDN博客_c输入字符串 可以用的函数 substr substr有2种用法&#xff1a; 假设&#xff1a;string s "0123456789"; string sub1 s.substr(5); //只有一个数字5表示从下标为5开始一直到结尾&#xff1a;sub1 &…

MATLAB-字符串

本节我们学习如何在MATLAB中创建一个字符串。 例如&#xff1a; my_string 搬砖工程师domi MATLAB执行上述语句&#xff0c;返回以下结果&#xff1a; my_string 搬砖工程师domi MATLAB 认为所有变量&#xff0c;数组和字符串被视为字符数组。 让我们使用命令检查上面创建…

c语言:动态输入字符串数组

考研题中经常会遇到给定一条英文句子&#xff0c;让我们对其每个单词进行操作&#xff0c;不同于对整型数据操作&#xff0c;字符串在c语言中必须存放到数组中&#xff0c;无形之中又给考题增加了难度 一般情况下&#xff0c;字符串数组都以二维数组或指针数组定义&#xff0c…

用scanf_s输入字符串

用的是vs2019。 为了安全&#xff0c;scanf_s输入字符串时需要加一个数字来限制最多读取的字符数。 错误示例&#xff1a; char* str[100]; scanf_s("%s",str);这样写编译器没有报错&#xff0c;但是运行会出错&#xff0c;debug显示 正确写法&#xff1a; char…

写一函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。

写一函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。 解题思路&#xff1a; 字符串以\0作为结尾&#xff0c;则从第一个字符开始向后移动遇到\0认为字符串结束。 答案&#xff1a; #include <stdio.h> int mystrlen(char *str) {int len 0;char *pt…