简体   繁体   English

是否可以使用for循环索引访问结构的元素?

[英]Is it possible to access elements of structure using for loop indexing?

I tried to form an ip-packet by user input. 我试图通过用户输入来形成一个IP数据包。 I did till L4 only. 我只做到L4。 l7 header including data I took as string. l7标头,包括我作为字符串的数据。 For L4 header user has to give values of different fields of l4, I tried converting them into sting and appending to packet. 对于L4标头,用户必须提供l4不同字段的值,我尝试将它们转换为字符串并追加到数据包。 I wanted to similar for layer 3 too. 我也想为第3层做类似的事情。

Its working fine, but in code I endup in writing similar code for different fields of L4. 它的工作正常,但在代码中,我最终为L4的不同领域编写了类似的代码。 I mentioned them in blocks in code. 我在代码块中提到了它们。 Is possible to convert all 4 blocks into single block using for loop. 可以使用for循环将所有4个块转换为单个块。

code part is: 代码部分是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct l4{
    unsigned short source_port;
    unsigned short dest_port;
    unsigned int length;
    unsigned short checksum;
}l4_struct;

void append_l7(char *packet , FILE *fp) {
    char l7_packet[255];
    fscanf(fp , "%[^\n]%*c" , l7_packet);
    strcpy(packet , l7_packet);
}

void append_l4(char *packet , FILE *fp) {
    char l4_header_string[255] , buf[255];
    memset(buf  , 0 ,  255);
    l4_struct l4_header;

//block 1
    fscanf(fp , "%hd" , &l4_header.source_port);
    sprintf(buf , "%x" , l4_header.source_port);
    strcpy(l4_header_string , buf);
    memset(buf  , 0 ,  255);

//block 2
    fscanf(fp , "%hd" , &l4_header.dest_port);
    sprintf(buf , "%s %.4x" , l4_header_string , l4_header.dest_port);
    strcpy(l4_header_string , buf);
    memset(buf  , 0 ,  255);

//block 3
    fscanf(fp , "%d" , &l4_header.length);
    sprintf(buf , "%s %.4x" , l4_header_string , l4_header.length);
    strcpy(l4_header_string , buf);
    memset(buf  , 0 ,  255);

//block 4
    fscanf(fp , "%hd" , &l4_header.checksum);
    sprintf(buf , "%s %.4x" , l4_header_string , l4_header.checksum);
    strcpy(l4_header_string , buf);
    memset(buf  , 0 ,  255);

//    strcat(l4_header_string , packet);
    sprintf(buf , "%s %s" , l4_header_string , packet);
    strcpy(packet , buf);
}

void append_l3(char *packet , FILE *fp) {

}

int main() {
    FILE *fp = fopen("input_packet.txt" , "r");
    int packet_size = 255; //We can take from user also
    char *packet = (char *)calloc(packet_size , sizeof(char));

    append_l7(packet  , fp);
    append_l4(packet , fp);
//    append_l3(packet , fp);

    //printing packet
    printf("\nPacket:%s\n" , packet);
//    printf("%hd\n%d\n" , sizeof(unsigned short) , sizeof(unsigned int));
    free(fp);
    free(packet);
}

And input_packet.txt is 而input_packet.txt是

ab c9 01 00 00 01 00 00 00 00 00 00 09 6d 63 63 6c 65 6c 6c 61 6e 02 63 73 05 6d 69 61 6d 69 03 65 64 75 00 00 01 00 01
58759
53
48
58144

Output: 输出:

Packet:e587 0035 0030 e320 ab c9 01 00 00 01 00 00 00 00 00 00 09 6d 63 63 6c 65 6c 6c 61 6e 02 63 73 05 6d 69 61 6d 69 03 65 64 75 00 00 01 00 01

I want append_l4( ) function something like below: 我想要append_l4( )函数如下所示:

char **dptr = (char **) malloc(sizeof(char *) * 4);
dptr[0] = "source_port";
dptr[1] = "dest_port";
dptr[2] = "length";
dptr[3] = "checksum";

void append_l4(char *packet , FILE *fp) {
    char l4_header_string[255] , buf[255];
    memset(buf  , 0 ,  255);
    l4_struct l4_header;

    for(i = 0; i < 4; i++){
        fscanf(fp , "%(this type varies)" , &l4_header.dptr[i]);
        sprintf(buf , "%s %.4x" , l4_header_string , l4_header.dptr[i]);
        strcpy(l4_header_string , buf);
        memset(buf  , 0 ,  255);
    }

//    strcat(l4_header_string , packet);
    sprintf(buf , "%s %s" , l4_header_string , packet);
    strcpy(packet , buf);
}

Is it possible? 可能吗? If yes, Please suggest me how can I achieve this. 如果是,请建议我该如何实现。

Iterating over a struct in C++ is similar but it is in C++. 在C ++中迭代一个结构是相似的,但是在C ++中。

My suggestion is that you try using a union , which will allow you to store "different" data types in the same memory location. 我的建议是尝试使用union ,这将允许您将“不同”的数据类型存储在同一内存位置。 Nonetheless, you'll have to handle your input data equally for all possible field size (which seems to be what you want). 但是,对于所有可能的field大小(这似乎是您想要的),您必须平等地处理输入数据。 I have done that myself for building TCP packets and the following structure is pretty useful (specially for copy operations). 我自己完成了构建TCP数据包的工作,以下结构非常有用(特别是用于复制操作)。

union packet_u
{
  uint8_t a[__TOTAL_STRUCT_SIZE__];
  struct
  {
      uint16_t field1;
      uint16_t field2;
      uint32_t field3;
      uint16_t field4;
  }
};

It should be straightforward to read the input file and save it on your structure, so I'll leave you to work on this idea. 读取输入文件并将其保存在您的结构中应该很简单,所以我将让您继续研究这个想法。 Also, you can change the smallest size you want to iterate over (ie, uint8_t a[...] ). 另外,您可以更改要迭代的最小大小(即uint8_t a[...] )。

That snprintf + memcpy + memset(..., 0, ...) is just nonsense. snprintf + memcpy + memset(...,0,...)只是胡说八道。 You create a buffer, read to that buffer, than copy from that buffer to another buffer, then zero that buffer... Why not copy to the destination buffer all the time? 创建一个缓冲区,读取该缓冲区,然后从该缓冲区复制到另一个缓冲区,然后将该缓冲区归零...为什么不一直复制到目标缓冲区? snprintf returns the number of characters written, you can concatenate it's output by manipulating the position of it's first argument: snprintf返回写入的字符数,您可以通过操纵其第一个参数的位置来连接其输出:

size_t pos = 0;

pos += sprintf(&l4_header_string[pos], "%x", l4_header.source_port);
pos += sprintf(&l4_header_string[pos], " %.4x", l4_header.<next field>);
pos += sprintf(&l4_header_string[pos], " %.4x", l4_header.<next field>);
pos += sprintf(&l4_header_string[pos], " %.4x", l4_header.<next field>);

Anyway, you can just do one scanf and one snprintf: 无论如何,您只能执行一个scanf和一个snprintf:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

typedef struct l4{
    unsigned short source_port;
    unsigned short dest_port;
    unsigned int length;
    unsigned short checksum;
}l4_struct;

void append_l7(char *packet , FILE *fp) {
    fgets(packet, 255, fp);
}

void append_l4(char *packet , FILE *fp) {
    l4_struct l4_header;

    fscanf(fp , "%hd %hd %d %hd" , 
        &l4_header.source_port,
        &l4_header.dest_port,
        &l4_header.length,
        &l4_header.checksum);
    // we can't snprintf(buffer, "%s", buffer) so we need to create a packet copy
    char *packetcopy = strdup(packet);
    assert(packetcopy != NULL);
    sprintf(packet, "%x %.4x %.4x %.4x %s",
        l4_header.source_port, 
        l4_header.dest_port,
        l4_header.length, 
        l4_header.checksum,
        packetcopy);
    free(packetcopy);
}

int main() {
    FILE *fp = fopen("input_packet.txt" , "r");
    int packet_size = 255; //We can take from user also
    char *packet = (char *)calloc(packet_size , sizeof(char));

    append_l7(packet, fp);
    append_l4(packet, fp);

    printf("Packet:%s\n" , packet);

    // free(fp); ????????
    fclose(fp);
    free(packet);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM