fget函数的用法
fgets() 函数用来从指定的文件中读取一个字符串,并保存到字符数组中。
str 为字符数组,n 为要读取的字符数目,fp 为文件指针。
char *fgets(char *str, int n, FILE *stream)
返回值:读取成功时返回字符数组首地址,也即 str;读取失败时返回 NULL;如果开始读取时文件内部指针已经指向了文件末尾,那么将读取不到任何字符,也返回 NULL。
返回值
如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。
如果发生错误,返回一个空指针。
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main()
{
FILE *p;
char str[N + 1] = {0};
p = fopen("a.txt", "r");
if (p == NULL) {
printf("open file faild \n");
}
while ((fgets(str, N, p)) != NULL) {
printf("%s", str);
}
fclose(p);
return 0;
}
fgetc函数的用法
fgetc 是 file get char 的缩写,意思是从指定的文件中读取一个字符。
fgetc() 的用法为:int fgetc (FILE *fp);
fp 为文件指针。fgetc() 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF。
EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。fgetc() 的返回值类型之所以为 int,就是为了容纳这个负数(char不能是负数)。
表示从a.txt
文件中读取一个字符,并保存到变量 ch 中
#include<stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char ch;
//如果文件不存在,给出提示并退出
if( (fp=fopen("a.txt", "r")) == NULL ){
puts("Fail to open file!");
exit(0);
}
//每次读取一个字节,直到读取完毕
while((ch = fgetc(fp)) != EOF ) {
putchar(ch);
}
fclose(fp);
return 0;
}
一道简单的字符串题目,就是单词逆序,不是完全字符串完全逆序
上面是输入
abc def 123 456
下面是输出
cba fed 321 654
#include<stdio.h>
#include<string.h>
/*实现思路: 例如 abc word, 先找到空格,然后逆序就得到cba,word没有空格,
就找到空格后的第一个字符,和最后一个字符,逆序就得到drow */
int main(int argc, char *argv[])
{
char str[100] = {0};
int len = 0;
int len2 = 0;
gets(str); /* 输入字符串*/
len = strlen(str); /* 计算总的字符串的长度 */
for (int i = 0; i < len; i++) { /* 遍历字符串中的字符 */
if (str[i] == ' ') { /* 如果找到了空格 */
for (int j = i - 1; j >= len2; j--) { /* 找到来空格, i-1得到单词的最后一个字符,然后逆序输入(j--) */
printf("%c", str[j]);
}
printf(" ");
len2 = i + 1; /* 得到了最后一个单词的第一个字符 */
}
if (i == len - 1) { /* 如果遍历到了最后一个单词的最后一个字符的时候 */
for (int j = i; j >= len2; j--) { /* 逆序输入最后一个单词 */
printf("%c", str[j]);
}
}
}
printf("\n");
}
运行结果如下:
C语言结构体函数指针
#include <stdio.h>
#include <malloc.h>
typedef struct Value //只有结构体变量才分配地址,而结构体的定义是不分配空间的
{
int dat;
char str;
}Value;
typedef struct Fun{ //只有结构体变量才分配地址,而结构体的定义是不分配空间的
int a,b;
int m,n;
void(*print)(void); //函数指针,是一个指针变量,指向某个函数的地址,
int (*add)(int a,int b); //即可实现该函数的功能.
int (*returnVal)(void);
void(*test)(int m,int n);
}Fun;
/*****************************************************/
void print(void)
{
printf("Print success!\n");
}
int add(int a,int b)
{
return a+b;
}
int returnVal(void)
{
return 1024;
}
void TEST(int j,int k)
{
printf("TEST():%d\n",j+k);
}
/****初始化一个结构体变量****/
Fun f = {
.a = 1,
.b = 5,
.m = 10,
.print = print,
.add = add,
.returnVal = returnVal,
.test = TEST //将结构体test函数地址,指向TEST真正存在的函数
};
/*****************************/
int main(void)
{
Value *va = (Value*)malloc(sizeof(Value)); //初始化一个Value结构体的变量
Fun *t = (Fun*)malloc(sizeof(Fun));
t->n = 13; //等价于t->n = 13;
va->dat = 12;
printf("va->dat:%d\n",va->dat);
printf("t->n:%d\n",t->n);
print();
printf("%d\n",f.add(f.a,f.b));
printf("%d\n",f.returnVal());
f.test(f.m,18); //传入参数既可以是结构体变量f里的值,也可以外部输入
TEST(50,100);
return 0;
}
运行结果:
C语言日志
#define DEBUG1(format,args...) do { \
printf("%d %s "format, __LINE__, __func__, ##args);\
} while(0)
#define DEBUG(format, ...) do { \
printf("%s(%d):", __func__, __LINE__); \
printf(format, ##__VA_ARGS__); \
printf("\r\n"); \
} while (0)
更加完整的一个日志函数
#include <stdio.h>
#define Print(x, y) do { \
printf("%d\n", x); \
printf("%d\n", y); \
} while(0)
int dbg_level = 1;
#define LAN_HOST_TRACE_FLAG 1
#define DEBUG_TRACE(x, y) do { \
if ( dbg_level&(x) ) { \
printf("[hostinfo]:"); \
printf y; \
fflush(stdout);} \
} while(0)
int main()
{
int interval = 1;
DEBUG_TRACE(LAN_HOST_TRACE_FLAG, ("[%s %d]:interval = %d.\n", __func__, __LINE__, interval));
return 0;
}
一个小demo需求:提取uci命令(uci show wireless.default_radio0)里面的ssid,加密,以及密码,把内容copy到txt文件调试,实现后在虚拟机效果一样。
txt文本内容:
wireless.default_radio0=wifi-iface
wireless.default_radio0.device='radio0'
wireless.default_radio0.network='lan'
wireless.default_radio0.mode='ap'
wireless.default_radio0.ssid='Hiwooya'
wireless.default_radio0.encryption='psk2'
wireless.default_radio0.key='1234567890'
C语言代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义一个结构体来存储配置信息
struct wireless_config {
char ssid[128];
char encryption[128];
char key[128];
};
// 函数:从字符串中提取值
int extract_value(const char *line, char *value, int value_size)
{
//strchr`函数用于在一个字符串中查找第一次出现的指定字符,并返回从该字符到字符串结束的所有字符的指针。
//如果未找到指定字符,函数返回`NULL`
const char *start = strchr(line, '\'');
const char *end = NULL;
int len = 0;
if (start != NULL) {
start++;
end = strchr(start, '\'');
if (end != NULL) {
len = end - start; //计算得到`start`和`end`之间的距离,这个距离正是被引号包围的文本的长度。
//在C语言中,两个指针相减的结果是它们之间相差的元素个数,
//因此这里的`len`代表了两个单引号之间字符的数量。
if (len < value_size) {
strncpy(value, start, len);
value[len] = '\0';
return 1;
}
}
}
return 0; // 未提取值
}
// 主函数
int main()
{
FILE *file = NULL;
char line[256] = {0};
struct wireless_config config = {0}; // 初始化结构体
// 打开文件
file = fopen("123.txt", "r");
if (!file) {
perror("Failed to open file");
return EXIT_FAILURE;
}
// 逐行读取文件内容
while (fgets(line, sizeof(line), file)) {
if (strstr(line, "wireless.default_radio0.ssid=")) {
extract_value(line, config.ssid, sizeof(config.ssid));
} else if (strstr(line, "wireless.default_radio0.encryption=")) {
extract_value(line, config.encryption, sizeof(config.encryption));
} else if (strstr(line, "wireless.default_radio0.key=")) {
extract_value(line, config.key, sizeof(config.key));
}
}
// 关闭文件
fclose(file);
// 显示提取的配置信息
printf("SSID: %s\n", config.ssid);
printf("Encryption: %s\n", config.encryption);
printf("Key: %s\n", config.key);
return 0;
}
运行效果:
sscanf函数的用法
sscanf()` 函数是 C 标准库 `<stdio.h>` 中的一个函数,用于从字符串中按照指定的格式读取数据,类似于 `scanf()` 函数,但 `sscanf()` 从字符串中读取数据,而不是从标准输入(键盘)读取。
int sscanf(const char *str, const char *format, ...);
- `str`:要读取数据的字符串。
- `format`:格式字符串,指定了要读取的数据的类型和格式,就像 `scanf()` 中的格式字符串一样。
- `...`:要读取的数据存储位置,与 `scanf()` 类似,可以是各种类型的指针。
`sscanf()` 函数会尝试根据指定的格式从字符串 `str` 中读取数据,并将读取到的数据存储到提供的位置中。它的返回值是成功匹配并读取的参数个数,如果没有匹配成功,则返回值为 0。
#include <stdio.h>
int main()
{
char str[] = "Hello 123 45.67";
char word[10];
int num1, num2;
float num3;
// 从字符串中读取数据
int count = sscanf(str, "%s %d %f", word, &num1, &num3);
// 打印读取的数据
printf("Read %d items:\n", count);
printf("Word: %s\n", word);
printf("Integer: %d\n", num1);
printf("Float: %f\n", num3);
return 0;
}
运行效果:
实际遇到情况,需要提取部分参数,那么如何跳过部分参数。
我们现在只需要提取ip flag address device, 那么如何实现呢
我们只需要在%s中间加上*号,就可以跳过,如何还要跳过前面的部分,如0x2,只需要2,在格式化格式前面加上0x。如再遇到sscanf函数,忘记怎么用,跑一下下面的Demo即可。
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
char line[256] = {0};
char mac_str[18] = {0}, ip_str[16] = {0}, dev_name[6 + 1] = {0};
int arg_num = 0;
unsigned int flag = 0;
fp = fopen("/proc/net/arp", "r");
if (fp == NULL) {
printf("fopen open faild\n");
return 0;
}
while (fgets(line, sizeof(line), fp)) {
//IP address HW type Flags HW address Mask Device
//192.168.1.1 0x1 0x2 00:11:22:33:44:55 * eth0
arg_num = sscanf(line, "%s 0x%*x 0x%x %s %*s %s", ip_str, &flag, mac_str, dev_name);
if (arg_num == 4) {
printf("ip:%s flags:%x address:%s device:%s\n", ip_str, flag, mac_str, dev_name);
}
}
fclose(fp);
return 0;
}
运行效果: