从文件中获取特定内容并将其存储在变量中。到目前为止,我知道我可以将文件内容转换为字符串。但我不确定如何从我转换的字符串中“提取”内容并需要一些帮助。
原始文件如下所示:
XXXXXX
XXXXX
Addr = 12:23:34:45:45
XXX
XXX
我需要将 Addr 提取并存储为字符串。想要查找前缀 Addr =
并将其复制到缓冲区中。但我不知道我该怎么做...
到目前为止,我的代码如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
//So far I'm looking for it using the MAC addr format
const char *get_mac_addr(char *str, char *dest) {
if (str == NULL)
return 0;
char *start = NULL;
int token_count = 0;
char *ptr = str;
if (*ptr && *(ptr + 1)) // skip two chars in the beginning of the string
ptr += 2;
else
return 0;
while (*ptr != '\0' && *ptr != '\n' && *ptr != '\r') {
if (token_count == 5)
break;
/* if ':' found and previous two characters are hexidecimal digits then
the substring could be part of MAC
*/
if (*ptr == ':' && isxdigit(*(ptr - 1)) && isxdigit(*(ptr - 2))) {
token_count++;
if (start == NULL)
start = ptr - 2;
int i = 0;
while (*ptr != '\0' && i++ < 3)
ptr++;
} else {
start = NULL;
token_count = 0;
ptr++;
}
}
strcpy(dest, start);
return dest;
}
const char *file2str(){
/* declare a file pointer */
FILE *infile;
char *buffer;
long numbytes;
char dest[18];
/* open an existing file for reading */
infile = fopen("~/Desktop/file.config", "r");
/* quit if the file does not exist */
//if (infile == NULL)
// return 1;
/* Get the number of bytes */
fseek(infile, 0L, SEEK_END);
numbytes = ftell(infile);
/* reset the file position indicator to
the beginning of the file */
fseek(infile, 0L, SEEK_SET);
/* grab sufficient memory for the
buffer to hold the text */
buffer = (char *)calloc(numbytes, sizeof(char));
/* memory error */
//if(buffer == NULL)
// return 1;
/* copy all the text into the buffer */
fread(buffer, sizeof(char), numbytes, infile);
fclose(infile);
/* confirm we have read the file by
outputing it to the console */
printf("The file called test.dat contains this text\n\n%s", buffer);
//memset(dest, '/0', sizeof(dest));
get_mac_addr(buffer, dest);
/* free the memory we used for the buffer */
//free(buffer);
printf("Dest is \n\n%s", dest);
return dest;
}
int main() {
printf(file2str);
return 0;
}
答案 0 :(得分:1)
非常感谢您的帮助。请和我一起裸露,因为我不太擅长 c 编程。我想将主函数转换为一个函数,这样我就可以直接调用它并返回一个字符串。我将主函数转换如下,但我不知道为什么当我打印它时,没有任何显示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
const char *MACadd()
{
char buf[256];
char *addr = NULL;
FILE *in = xfopen("~Desktop/file.config", "r");
while( fgets(buf, sizeof buf, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + sizeof buf - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
//printf("addr = %s\n", addr);
return addr;
}
FILE *xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int main(){
printf("%s", MACadd());
return 0;
}
答案 1 :(得分:1)
您可以使用 fgets
函数逐行读取文件,然后使用 sscanf
函数提取相关部分,如下所示:
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#define ISXDGT(c) isxdigit((unsigned char)(c))
static bool is_macaddr (const char *s)
{
return ISXDGT(s[0]) && ISXDGT(s[1]) && s[2] == ':'
&& ISXDGT(s[3]) && ISXDGT(s[4]) && s[5] == ':'
&& ISXDGT(s[6]) && ISXDGT(s[7]) && s[8] == ':'
&& ISXDGT(s[9]) && ISXDGT(s[10]) && s[11] == ':'
&& ISXDGT(s[12]) && ISXDGT(s[13]) && s[14] == ':'
&& ISXDGT(s[15]) && ISXDGT(s[16]);
}
bool get_macaddr_from_file (const char *filename, char *macaddr)
{
char line[4096];
bool done = false;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open the file '%s'\n", filename);
return false;
}
while (fgets(line, sizeof line, fp) != NULL) {
/* Modify the prefix (" Addr = " here) at your convenience */
if (sscanf(line, " Addr = %17s", macaddr) == 1 && is_macaddr(macaddr)) {
done = true;
break;
}
}
fclose(fp);
return done;
}
int main (void)
{
char macaddr[18];
if (get_macaddr_from_file("file.conf", macaddr)) {
printf("MAC: %s\n", macaddr);
}
}
答案 2 :(得分:0)
char *extract(const char *str, char *buff)
{
char *addr = strstr(str, "Addr");
if(addr)
{
addr += sizeof("Addr") - 1;
while(!isdigit((unsigned char)*addr))
{
if(*addr == '\n' || !*addr)
{
addr = NULL;
break;
}
addr++;
}
if(addr)
{
while(*addr && *addr != '\n' && (isdigit(*addr) || *addr == ':'))
{
*buff++ = *addr++;
}
*buff = 0;
}
}
return addr ? buff : NULL;
}
void main(int argc, char** argv)
{
char *str = "XXXXXX\nXXXXX\n\nAddr = 12:23:234:145:45 \nXXX\nXXX\n";
char mac[30];
if(extract(str,mac)) printf("Hurray!!! `%s`\n", mac);
else printf("MIsareble failure\n");
}
答案 3 :(得分:0)
如果您不想将自己限制为固定的最大行长度,这会有点棘手,但执行以下操作可能就足够了:
#define ADDRLEN 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
int
main(int argc, char **argv)
{
char buf[256];
char *addr = NULL;
FILE *in = xfopen(argc > 1 ? argv[1] : "-", "r");
while( fgets(buf, sizeof buf, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + sizeof buf - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
printf("addr = %s\n", addr);
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
要将其分解为函数,您需要小心一点。在您的尝试中,您已将引用传递回函数返回后不再存在的局部变量。也许你想要这样的东西:
#define ADDRLEN 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
const char *
MACadd(const char *path, char *buf, size_t s)
{
char *addr = NULL;
FILE *in = xfopen(path, "r");
while( fgets(buf, s, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + s - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
return addr;
}
FILE *xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(void)
{
char buf[256];
printf("%s", MACadd("input", buf, sizeof buf));
return 0;
}
答案 4 :(得分:0)
我认为这比你做的更容易,一旦你移动了字符串中的文件内容,使用 strstr() - 这里是描述 http://www.cplusplus.com/reference/cstring/strstr/ - 找到“addr =”然后获取字符串从那里到字符“\n” 按照这个例子
#include<string.h>
#include<stdio.h>
#define endchrptr(ptr1, ptr2, ptr3) (ptr1 < ptr2 ? (ptr1<ptr3?ptr1:ptr3) : (ptr2<ptr3?ptr2:ptr3))
bool get_mac_addr(const char* source, char *dest) {
if(source!=NULL&&dest!=NULL) {
char* addr_pointer=strstr(source, "Addr = ")+7;//find where the address start
char* end_addr_pointer=endchrptr(strchr(addr_pointer, '\n'), strchr(addr_pointer, '\r'), strchr(addr_pointer, '\0'));//find where the address ends
if(end_addr!=NULL) {
for(int i=0; i<end_addr_pointer-addr_pointer; ++i) {//copy the address
dest[i]=addr_pointer[i];
}
dest[end_addr_pointer-addr_pointer],
}
else return false;
}
else return false;
}
int main()
{
char *str = "XXXXXX\nXXXXX\n\nAddr = 12:23:234:145:45 \nXXX\nXXX\n";
char mac[30];
get_mac_addr(str, mac);
printf("%s", mac);
}
我刚刚在 DevC++ 中尝试过,它可以工作。 让我知道它是否有效。
答案 5 :(得分:0)
代码中存在多个问题:
fopen("~/Desktop/file.config", "r");
会失败,因为文件名中的 ~
没有被 fopen
扩展到主目录,这是命令 shell 的一个特性。改用完整路径,或将文件名作为参数。
您没有检查 fopen()
失败:将空流指针传递给 fseek
具有未定义的行为,并且可能会导致程序崩溃。
printf(file2str);
是一个重大错误:您尝试将函数中的字节用作格式字符串,您将得到垃圾输出,并且可能由于未定义的行为而导致崩溃。改用 printf("%s\n", file2str());
。
对于这个问题,不需要一次读取内存中的整个文件,一次读取一行就简单多了。此外,您没有为空终止符分配足够的内存,因此使用 buffer
作为 C 字符串时会出现未定义的行为。
get_mac_addr
太复杂了:您可以使用 strstr
来定位字符串 "Addr = "
并提取以下单词。
这是一个更简单的版本:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
const char *get_mac_address(const char *str, char *dest) {
if (!strncmp(buf, "Addr = ", 7)) {
const char *p = buf + 7;
for (i = 0; i < 17; i++) {
if (i % 3 == 2) {
if (p[i] != ':')
break;
} else {
if (!isxdigit((unsigned char)p[i]))
break;
}
}
if (i == 17 && !isalnum((unsigned char)p[i]) {
memcpy(dest, p, 17);
dest[17] = '\0';
return dest;
}
}
return NULL;
}
int main() {
char buf[256];
char address[20];
FILE *fp = fopen("/home/ImTrying/Desktop/file.config", "r");
if (fp != NULL) {
while (fgets(fp, buf, sizeof buf)) {
if (get_mac_address(buf, address)) {
printf("Dest is %s\n", address);
break;
}
}
fclose(fp);
}
return 0;
}