从主字符串 C 中分割子字符串

时间:2021-02-04 17:34:32

标签: c string

从文件中获取特定内容并将其存储在变量中。到目前为止,我知道我可以将文件内容转换为字符串。但我不确定如何从我转换的字符串中“提取”内容并需要一些帮助。

原始文件如下所示:

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;
}

6 个答案:

答案 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");
}

https://godbolt.org/z/6TjK8b

答案 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;
}