因此,我必须创建一个 .c 文件,按升序对 IP 地址进行排序,并对所有 IP 地址进行计数。考虑到存在 ip.txt 文件,同时包含如下内容(IP 地址和错误代码)
127.0.0.0 500
127.0.0.0 400
127.0.0.1 300
127.0.0.2 100
请提出一些建议如果您擅长编程,请提前谢谢!
以下是我进行的尝试,请随意建议和修改代码以获得完美的输出。
尝试过的代码附加在图像文件中,我希望整理 IP 地址并在输出控制台中给出从最大到最小的 IP 地址计数。
下面的文件_操作_代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char * line = NULL;
size_t len = 0;
ssize_t read;
int count=0, totalCh=0;
FILE *fp = fopen("ip.txt", "r");
if(fp == NULL){
printf("IP File does not exist!\n");
return -1;
}
while ((read = getline(&line, &len, fp)) != -1) {
count++;
totalCh+=read;
printf("line of length: %zu\n", read);
printf("line content: %s", line);
}
printf("Total number of lines=%d\n", count);
printf("Total number of characters=%d\n", totalCh);
// logic to fetch IP addr and sort out and give count to output console pending
fclose(fp);
if (line)
free(line);
return 0;
}
如果您编写了合适的比较函数,那么您可以使用
qsort
对数据进行排序。
但你可能连这个都不需要。以下是安全地从文件获取结果的示例。
IP (v4) 地址是一组 4 个八位字节。对于主机,您不能将
0
作为第一个八位位组或最后一个八位位组。而且你也不可能拥有所有的---255
。 0
是网络地址,255
是广播地址。
Packet
表示有效的IP和代码typedef struct
{
char ip[16];
int a, b, c, d; // octets
unsigned code;
} Packet;
这对于快速测试来说是可以的,并且让生活变得更轻松。因为这只是玩具,我们可以同时拥有八位字节的字符串和十进制值。
此函数
so_compare()
比较 2 Packet
,如果 -1
按排序顺序位于 one
之前,则返回 other
。如果 +1
在 one
之后,则 other
。这就是您使用 qsort
中 stdlib 中的 C
对它们进行排序所需的全部内容。
int so_compare(Packet* one, Packet* other)
{
if (one == NULL) return 0;
if (other == NULL) return 0;
// 1
if (one->a < other->a) return -1;
if (one->a > other->a) return 1;
// 2
if (one->b < other->b) return -1;
if (one->b > other->b) return 1;
// 3
if (one->c < other->c) return -1;
if (one->c > other->c) return 1;
// 4
if (one->d < other->d) return -1;
if (one->d > other->d) return 1;
// code
if (one->code < other->code) return -1;
if (one->code > other->code) return 1;
// stable
return 1;
}
您只需为输入文件中的每个有效行获取一个即可。
这可以非常简单:我们只需要一个有效 IP 和有效代码。
sscanf()
在这里很好,因为我们可以一次解析所有 5 个值。
so_get_packet()
从输入文件中获取一行并返回一个有效的Packet
,用几行代码。
提取八位字节的值,验证它们,填充新的
Packet
,我们就完成了。
Packet* so_get_packet(const char* addr)
{
int a, b, c, d;
int code;
int res = 0;
const char* mask = "%3d.%3d.%3d.%3d %3d";
res = sscanf(addr, mask, &a, &b, &c, &d, &code);
if (res != 5) return NULL;
if ((a < 1) || (a > 254)) return NULL;
if ((b < 0) || (b > 254)) return NULL;
if ((c < 0) || (c > 254)) return NULL;
if ((d < 1) || (d > 254)) return NULL;
Packet* pck = malloc(sizeof(Packet));
if (pck == NULL) return NULL;
sprintf(pck->ip, "%d.%d.%d.%d", a, b, c, d);
pck->a = a, pck->b = b, pck->c = c, pck->d = d;
pck->code = code;
return pck;
}
这是
C
。通过组合和遏制,生活变得更加轻松。考虑一系列数据包,我们可以使用如下的 Vector
来存储它们。
#define MAX_DATA 100
typedef struct
{
size_t size;
size_t limit;
Packet data[MAX_DATA];
} Vector;
所以程序只是一个问题
Packet
Vector
事物由于每个
Vector
都有一个 size
,我们总是知道到目前为止我们获得的地址数量。
qsort
数据因为我们一次只获取一行更有意义,所以按顺序插入它们......
int so_insert(Packet* pck, Vector* V)
{
if (pck == NULL) return -1;
if (V == NULL) return -2;
if (V->size == V->limit) return -3; // full
if (V->size == 0) // was empty
{
V->data[0] = *pck;
V->size = 1;
return 0;
}
for (size_t pos = V->size; pos > 0; --pos)
{ // insert in position
if (so_compare(pck, &V->data[pos - 1]) > 0)
{ // 'pos' is the position
V->data[pos] = *pck;
++V->size;
return 0;
}
V->data[pos] = V->data[pos - 1];
}; // for
V->data[0] = *pck;
++V->size;
return 0;
}
这里并不奇怪:如上所述,
so_insert()
按顺序将Packet
插入到Vector
中,因此当我们到达输入末尾时,所有行都已在Vector
中排序。
此
so_consume_file()
执行预期操作:获取文件名并返回地址和代码的排序列表。或者 NULL
如果出现错误。
Vector* so_consume_file(const char* file_name)
{
FILE* in = fopen(file_name, "r");
if (in == NULL) return NULL;
// create array
Vector* data = so_create(MAX_DATA);
if (data == NULL) return NULL;
char buffer[256] = {0};
char* p = buffer;
int res = 0;
while ((p = fgets(buffer, sizeof(buffer), in)) != NULL)
{
Packet* pck = so_get_packet(buffer);
if (pck != NULL)
{
so_insert(pck, data);
free(pck);
}
};
fclose(in);
so_show_v(data, "final data ");
return data;
}
并且易于阅读:单个循环。如果一条线路有一个数据包,它就会进入列表。最后,列表被打印并销毁。
#define MAX_DATA 100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char ip[16];
int a, b, c, d; // octets
unsigned code;
} Packet;
typedef struct
{
size_t size;
size_t limit;
Packet data[MAX_DATA];
} Vector;
Vector* so_create(size_t);
Vector* so_destroy(Vector*);
Vector* so_consume_file(const char*);
int so_insert(Packet*, Vector*);
int so_show_v(Vector*,const char*);
Packet* so_get_packet(const char*);
int so_compare(Packet*, Packet*);
int so_show_p(Packet*, const char*);
// https://stackoverflow.com/questions/77597529/
// sort-out-ip-addrs-from-file-in-c-program
int main(int argc, char** argv)
{
const char* def_name = "in.txt";
char f_name[50];
if (argc < 2)
strcpy(f_name, def_name);
else { strcpy(f_name, argv[1]); }
fprintf(stderr, "input file is \"%s\"\n", f_name);
Vector* my_data = so_consume_file(f_name);
so_destroy(my_data);
return 0;
}
Vector* so_create(size_t limit)
{
if (limit > MAX_DATA) return NULL;
Vector* one = malloc(sizeof(Vector));
if (one == NULL) return NULL;
one->limit = limit;
one->size = 0;
return one;
}
Vector* so_destroy(Vector* del)
{
if (del == NULL) return NULL;
free(del);
return NULL;
}
Vector* so_consume_file(const char* file_name)
{
FILE* in = fopen(file_name, "r");
if (in == NULL) return NULL;
// create array
Vector* data = so_create(MAX_DATA);
if (data == NULL) return NULL;
char buffer[256] = {0};
char* p = NULL;
while ((p = fgets(buffer, sizeof(buffer), in)) != NULL)
{
Packet* pck = so_get_packet(buffer);
if (pck != NULL)
{
so_insert(pck, data);
free(pck);
}
};
fclose(in);
so_show_v(data, "final data ");
return data;
}
int so_insert(Packet* pck, Vector* V)
{
if (pck == NULL) return -1;
if (V == NULL) return -2;
if (V->size == V->limit) return -3; // full
if (V->size == 0) // was empty
{
V->data[0] = *pck;
V->size = 1;
return 0;
}
for (size_t pos = V->size; pos > 0; --pos)
{ // insert in position
if (so_compare(pck, &V->data[pos - 1]) > 0)
{ // 'pos' is the position
V->data[pos] = *pck;
++V->size;
return 0;
}
V->data[pos] = V->data[pos - 1];
}; // for
V->data[0] = *pck;
++V->size;
return 0;
}
int so_show_v(Vector* V, const char* msg)
{
if (V == NULL) return -1; // no vector
if (msg != NULL) printf("%s", msg);
printf("%llu/%llu elements\n", V->size, V->limit);
for (size_t i = 0; i < V->size; ++i)
{
so_show_p(&V->data[i], NULL);
}
printf("---\n\n");
return 0;
}
Packet* so_get_packet(const char* addr)
{
int a, b, c, d;
int code;
int res = 0;
const char* mask = "%3d.%3d.%3d.%3d %3d";
res = sscanf(addr, mask, &a, &b, &c, &d, &code);
if (res != 5) return NULL;
if ((a < 1) || (a > 254)) return NULL;
if ((b < 0) || (b > 254)) return NULL;
if ((c < 0) || (c > 254)) return NULL;
if ((d < 1) || (d > 254)) return NULL;
Packet* pck = malloc(sizeof(Packet));
if (pck == NULL) return NULL;
sprintf(pck->ip, "%d.%d.%d.%d", a, b, c, d);
pck->a = a, pck->b = b, pck->c = c, pck->d = d;
pck->code = code;
return pck;
}
int so_compare(Packet* one, Packet* other)
{
if (one == NULL) return 0;
if (other == NULL) return 0;
// 1
if (one->a < other->a) return -1;
if (one->a > other->a) return 1;
// 2
if (one->b < other->b) return -1;
if (one->b > other->b) return 1;
// 3
if (one->c < other->c) return -1;
if (one->c > other->c) return 1;
// 4
if (one->d < other->d) return -1;
if (one->d > other->d) return 1;
// code
if (one->code < other->code) return -1;
if (one->code > other->code) return 1;
// stable
return 1;
}
int so_show_p(Packet* P, const char* msg)
{
if (P == NULL) return -1;
if (msg != NULL) printf("%s", msg);
printf(" %16s %4d\n", P->ip, P->code);
return 0;
}
程序接受文件名作为输入。默认为 in.txt
SO> cat in.txt
stack overflow
127.0.0.0 500 not a host
127.0.0.0 400 not a host
127.0.0.1 300
127.0.0.2 100
127.0.0.2 99
127.0.0.2 101
127.0.0.2 100
SO> v1
input file is "in.txt"
final data 5/100 elements
127.0.0.1 300
127.0.0.2 99
127.0.0.2 100
127.0.0.2 100
127.0.0.2 101
---
SO>
SO>
SO> cat other.txt
127.0.0.10 500
127.0.0.100 400
127.0.0.1 300
127.0.0.2 100
127.0.0.2 101
127.0.0.2 101
10.0.0.1 200
10.0.0.1 201
10.0.0.92 200
10.0.0.2 200
SO> v1 other.txt
input file is "other.txt"
final data 10/100 elements
10.0.0.1 200
10.0.0.1 201
10.0.0.2 200
10.0.0.92 200
127.0.0.1 300
127.0.0.2 100
127.0.0.2 101
127.0.0.2 101
127.0.0.10 500
127.0.0.100 400
---
SO>
未经真正测试。希望它有助于展示一种以受控方式从原始文件数据到原型的方法。