In the below code, the file test.txt has the following data :
192.168.1.1-90
192.168.2.2-80
The output of this is not as expected.
I expect the output to be
192.168.1.1
90
192.168.2.2
80
Any help would be much appreciated.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char *result[10][4];
int i=0;
const char s[2] = "-";
char *value,str[128];
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else{
while(!feof(fp)){
if(fgets(str,sizeof(str),fp)){
/* get the first value */
value = strtok(str, s);
result[i][0]=value;
printf("IP : %s\n",result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
result[i][1]=value;
printf("PORT : %s\n",result[i][1]); //to be removed after testing
i++;
}}
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("\n%s\n",result[k][j]);
}
}
}
return(0);
}
You can try this solution. It uses dynamic memory instead, but does what your after.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 128
void exit_if_null(void *ptr, const char *msg);
int
main(int argc, char const *argv[]) {
FILE *filename;
char buffer[BUFFSIZE];
char *sequence;
char **ipinfo;
int str_size = 10, str_count = 0, i;
filename = fopen("ips.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error Reading File!");
exit(EXIT_FAILURE);
}
ipinfo = malloc(str_size * sizeof(*ipinfo));
exit_if_null(ipinfo, "Initial Allocation");
while (fgets(buffer, BUFFSIZE, filename) != NULL) {
sequence = strtok(buffer, "-\n");
while (sequence != NULL) {
if (str_size == str_count) {
str_size *= 2;
ipinfo = realloc(ipinfo, str_size * sizeof(*ipinfo));
exit_if_null(ipinfo, "Reallocation");
}
ipinfo[str_count] = malloc(strlen(sequence)+1);
exit_if_null(ipinfo[str_count], "Initial Allocation");
strcpy(ipinfo[str_count], sequence);
str_count++;
sequence = strtok(NULL, "-\n");
}
}
for (i = 0; i < str_count; i++) {
printf("%s\n", ipinfo[i]);
free(ipinfo[i]);
ipinfo[i] = NULL;
}
free(ipinfo);
ipinfo = NULL;
fclose(filename);
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
The key thing to understand is that char *strtok(char *str, const char *delim) internally modifies the string pointed to by str and uses that to store the result. So the returned pointer actually points to somewhere in str.
In your code, the content of str is refreshed each time when you parse a new line in the file, but the address remains the same. So after your while loop, the content of str is the last line of the file, somehow modified by strtok. At this time, result[0][0] and result[1][0] both points to the same address, which equals the beginning of str. So you print the same thing twice in the end.
This is further illustrated in the comments added to your code.
int main()
{
FILE *fp;
char *result[10][4];
int i=0;
const char s[2] = "-";
char *value,str[128];
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else{
while(!feof(fp)){
if(fgets(str,sizeof(str),fp)){
/* get the first value */
value = strtok(str, s);
// ADDED: value now points to somewhere in str
result[i][0]=value;
// ADDED: result[i][0] points to the same address for i = 0 and 1
printf("IP : %s\n",result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
// ADDED: value now points to somewhere in str
result[i][1]=value;
// ADDED: result[i][1] points to the same address for i = 0 and 1
printf("PORT : %s\n",result[i][1]); //to be removed after testing
i++;
}}
// ADDED: now result[0][0]==result[1][0], result[0][1]==result[1][1], you can test that
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("\n%s\n",result[k][j]);
}
}
}
return(0);
}
To get the expected output, you should copy the string pointed by the pointer returned by strtok to somewhere else each time, rather than just copy the pointer itself.
Related
Get specific content from a file and store it in a variable. So far I get that I can convert the file content into a string. But I'm not sure how can I 'extract' the content from the string I converted and would like some help.
The original file looks something like this:
XXXXXX
XXXXX
Addr = 12:23:34:45:45
XXX
XXX
I need to extract and store the Addr as a string. Want to look for the prefix Addr = and just copy it into a buffer. But I don't know how can I do it...
So far my code looks like below:
#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;
}
I really appreciate your help. Please bare with me as I'm not very good at c programming. I would like to convert the main function into one function so I can directly call it and return a string. I converted the main function as following, but I'm not sure why when I print it, there is nothing show up:
#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;
}
You could read the file line by line with the fgets function and use the sscanf function to extract the relevant portion like that:
#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);
}
}
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
This gets a little tricky if you don't want to restrict yourself to a fixed maximum line length, but it's probably sufficient to do something like:
#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;
}
To break this into a function, you need to be a little bit careful. In your attempt, you've passed back references to local variables which cease to exist after the function returns. Perhaps you want something like:
#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;
}
I think that is easier than you are doing, once you moved the file contnent in a string, use strstr() - here ther is the description http://www.cplusplus.com/reference/cstring/strstr/ - to find "addr = " and then get the string from there to the character "\n"
follow this example
#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);
}
I just tried in DevC++ and it works.
Let me know if it works.
There are multiple problems in the code:
fopen("~/Desktop/file.config", "r"); will fail because the ~ in the filename is not expanded to the home directory by fopen, it is a feature of the command shell. Use the full path instead, or take the filename as an argument.
you do not check for fopen() failure: passing a null stream pointer to fseek has undefined behavior and will probably crash the program.
printf(file2str); is a major mistake: you try to use the bytes from the function as a format string, you will get garbage output and possibly a crash because of undefined behavior. Use printf("%s\n", file2str()); instead.
there is no need to read the whole file in memory at once for this problem, just reading one line at a time is much simpler. Furthermore, you do not allocate enough memory for the null terminator, so you get undefined behavior with using buffer as a C string.
get_mac_addr is way too complicated: you could use strstr to locate the string "Addr = " and extract the following word.
Here is a simpler version:
#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;
}
I am trying a program in c to read a text file that contains array of characters or a string and find the number of occurrences of the substring called "GLROX" and say sequence found when it is found. And the "inputGLORX.txt" contains following string inside it.
GLAAAROBBBBBBXGLROXGLROXGLROXGLROXGLCCCCCCCCCCCCCCROXGGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROX
But i am getting wierd results. It would be great if some expert in C-programming helps me to solve this and thanks in advance.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define NUMBER_OF_STRINGS 40
#define MAX_STRING_SIZE 7
void seqFound()
{
printf("Sequence Found\n");
}
int main()
{
FILE *fp;
char buff[1000];
char strptrArr[NUMBER_OF_STRINGS] [MAX_STRING_SIZE];
const char *search = "GLROX";
fp = fopen("D:/CandC++/inputGLORX.txt", "r");
if(fp==NULL)
printf("It is a null pointer");
while(!feof(fp))
{
//fscanf(fp, "%s", buff);
fgets(buff, 1000,fp);
}
int len = strlen(buff);
printf("length is %d\n",len);
int count = 0;
char *store;
while(store = strstr(buff, search))
{
printf("substring is %s \n",store);
count++;
search++;
}
printf("count is %d\n",count);
while (count!=0) {
seqFound();
count--;
}
return 0;
}
As said in the comment, their are at least 2 problems in the code: your fgets will only fetch the last line (if it fetch one at all ? In any case, this is not what you want), and you are incrementing the search string instead of the buff string.
Something like this should fix most of your problems, as long as no lines in your file are longer than 999 characters. This will not work properly if you use the \n or NULL characters in your search string.
int count = 0;
while (fgets(buff, 1000, fp) != NULL)
{
char *temp = buff;
while ((temp = strstr(temp, search)))
{
printf("%d. %s\n", count + 1, temp);
count++;
temp++;
}
}
Here is a main for testing. I used argv to provide the input.txt and the search string.
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *fp;
char buff[1000];
char *search;
if (argc < 3)
return (-1);
search = argv[2];
if (search[0] == '\0')
return (-1);
if ((fp = fopen(argv[1], "r")) == NULL)
return (-1);
int count = 0;
while (fgets(buff, 1000, fp) != NULL)
{
char *temp = buff;
while ((temp = strstr(temp, search)))
{
printf("%d. %s\n", count + 1, temp);
count++;
temp++;
}
}
printf("Match found: %d\n", count);
return 0;
}
The way you search in buff is wrong, i.e. this code:
while(store = strstr(buff, search))
{
printf("substring is %s \n",store);
count++;
search++; // <------- ups
}
When you have a hit, you change search, i.e. the string you are looking for. That's not what you want. The search string (aka the needle) shall be the same all the time. Instead you want to move forward in the buffer buff so that you can search in the remainder of the buffer.
That could be something like:
int main()
{
const char* buff = "GLAAAROBBBBBBXGLROXGLROXGLROXGLROXGLCCCCCCCCCCCCCCROXGGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROXGLROX";
const char* search = "GLROX";
const char* remBuff = buff; // Pointer to the remainder of buff
// Initialized to be the whole buffer
const char* hit;
int cnt = 0;
while((hit = strstr(remBuff, search))) // Search in the remainder of buff
{
++cnt;
remBuff = hit + 1; // Update the remainder pointer so it points just 1 char
// after the current hit
}
printf("Found substring %d times\n", cnt);
return 0;
}
Output:
Found substring 15 times
I want to change my input.txt file to an integer array.
But sadly I keep missing one integer whenever new-line-character is met.
Following is my main()
int main(int args, char* argv[]) {
int *val;
char *STRING = readFile();
val = convert(STRING);
return 0;
}
Following is my file input function
char *readFile() {
int count;
FILE *fp;
fp = fopen("input.txt", "r");
if(fp==NULL) printf("File is NULL!n");
char* STRING;
char oneLine[255];
STRING = (char*)malloc(255);
assert(STRING!=NULL);
while(1){
fgets(oneLine, 255, fp);
count += strlen(oneLine);
STRING = (char*)realloc(STRING, count+1);
strcat(STRING, oneLine);
if(feof(fp)) break;
}
fclose(fp);
return STRING;
}
Following is my integer array function
int *convert(char *STRING){
int *intarr;
intarr = (int*)malloc(sizeof(int)*16);
int a=0;
char *ptr = strtok(STRING, " ");
while (ptr != NULL){
intarr[a] = atoi(ptr);
printf("number = %s\tindex = %d\n", ptr, a);
a++;
ptr = strtok(NULL, " ");
}
return intarr;
}
There are many issues.
This is a corrected version of your program, all comments are mine. Minimal error checking is done for brevity. intarr = malloc(sizeof(int) * 16); will be a problem if there are more than 16 numbers in the file, this should be handled somehow, for example by growing intarr with realloc, similar to what you're doing in readFile.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
char *readFile() {
FILE *fp;
fp = fopen("input.txt", "r");
if (fp == NULL)
{
printf("File is NULL!n");
return NULL; // abort if file could not be opened
}
#define MAXLINELENGTH 255 // define a constant rather than hardcoding "255" at several places
char* STRING;
char oneLine[MAXLINELENGTH];
STRING = malloc(MAXLINELENGTH);
int count = MAXLINELENGTH; // count mus be initialized and better declare it here
assert(STRING != NULL);
STRING[0] = 0; // memory pointed by STRING must be initialized
while (fgets(oneLine, MAXLINELENGTH, fp) != NULL) // correct usage of fgets
{
count += strlen(oneLine);
STRING = realloc(STRING, count + 1);
strcat(STRING, oneLine);
}
fclose(fp);
return STRING;
}
int *convert(char *STRING, int *nbofvalues) { // nbofvalues for returning the number of values
int *intarr;
intarr = malloc(sizeof(int) * 16);
int a = 0;
char *ptr = strtok(STRING, " \n"); // strings may be separated by '\n', or ' '
*nbofvalues = 0;
while (ptr != NULL) {
intarr[a] = atoi(ptr);
printf("number = %s\tindex = %d\n", ptr, a);
a++;
ptr = strtok(NULL, " \n"); // strings are separated by '\n' or ' '
} // read the fgets documentation which
// terminates read strings by \n
*nbofvalues = a; // return number of values
return intarr;
}
int main(int args, char* argv[]) {
int *val;
char *STRING = readFile();
if (STRING == NULL)
{
printf("readFile() problem\n"); // abort if file could not be read
return 1;
}
int nbvalues;
val = convert(STRING, &nbvalues); // nbvalues contains the number of values
// print numbers
for (int i = 0; i < nbvalues; i++)
{
printf("%d: %d\n", i, val[i]);
}
free(val); // free memory
free(STRING); // free memory
return 0;
}
I'm not sure what your requirement is, but this can be simplified a lot because there is no need to read the file into memory and then convert the strings into number. You could convert the numbers on the fly as you read them. And as already mentioned in a comment, calling realloc for each line is inefficient. There is room for more improvements.
Im new to c and am trying to understand pointers.
here I am opening a file and reading the lines given. Im trying to append these lines into an array and return it from the function. I dont seem to be appending or accessing the array correctly. output[count] = status; gives an error with mismatched char and char *.
Im essentially trying to get an array with a list of words given by a file where each element in the array is a word.
char *fileRead(char *command, char output[255]) {
int count = 0;
char input[255];
char *status;
FILE *file = fopen(command, "r");
if (file == NULL) {
printf("Cannot open file\n");
} else {
do {
status = fgets(input, sizeof(input), file);
if (status != NULL) {
printf("%s", status);
strtok(status, "\n");
// add values into output array
output[count] = status;
++count;
}
} while (status);
}
fclose(file);
return output;
}
I access fileRead via:
...
char commandArray[255];
char output[255];
int y = 0;
char *filename = "scriptin.txt";
strcpy(commandArray, fileRead(filename, output));
// read from array and pass into flag function
while (commandArray[y] != NULL) {
n = flagsfunction(flags, commandArray[y], sizeof(buf), flags.position, &desc, &parentrd, right, left, lconn);
y++;
...
Example of Read from file Line by line then storing nonblank lines into an array (array of pointer to char (as char*))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//for it does not exist because strdup is not a standard function.
char *strdup(const char *str){
char *ret = malloc(strlen(str)+1);
if(ret)
strcpy(ret, str);
return ret;
}
//Read rows up to 255 rows
int fileRead(const char *filename, char *output[255]) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("Cannot open file:");
return 0;
}
int count = 0;
char input[255];
while(count < 255 && fgets(input, sizeof(input), file)) {
char *line = strtok(input, "\n");
if(line)//When it is not a blank line
output[count++] = strdup(line);//Store replica
}
fclose(file);
return count;
}
int main(void){
char *output[255];//(`char *` x 255)
int number_of_read_line = fileRead("data.txt", output);
for(int i = 0; i < number_of_read_line; ++i){
printf("%s\n", output[i]);
free(output[i]);//Discard after being used
}
return 0;
}
In the below code, the file test.txt has the following data :
192.168.1.1-90
192.168.2.2-80
The output of this is not as expected. I expect the output to be
192.168.1.1
90
192.168.2.2
80
The current output is
192.168.2.2
80
192.168.2.2
80
I know that the pointer of str is pointing to the same address in the second iteration as well.
Im just not able to the problem.
Any help would be appreciated.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE * fp;
char * result[10][4];
int i = 0;
const char s[2] = "-";
char temp[50];
char * value, str[128], * string, t[20], x[29] = "192.168.2.2";
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else {
while (!feof(fp)) {
if (fgets(str, sizeof(str), fp)) {
/* get the first value */
value = strtok(str, s);
result[i][0] = value;
printf("IP : %s\n", result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
result[i][1] = value;
printf("PORT : %s\n", result[i][1]); //to be removed after testing
i++;
}
}
for (int k = 0; k < 2; k++) {
for (int j = 0; j < 2; j++) {
printf("\n%s\n", result[k][j]);
}
}
}
return (0);
}
I propose like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { IP = 0, PORT = 1};
int main(void){
FILE *fp;
char result[2][2][16];//2 lines, 2 kinds, 16:XXX.XXX.XXX.XXX+NUL
const char *s = "-";//delimiter
char *value, line[128];
int i=0;
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf("File doesn't exist\n");
exit(EXIT_FAILURE);
}
while(i < 2 && fgets(line, sizeof(line), fp)){
value = strtok(line, s);
strcpy(result[i][IP], value);
printf("IP : %s\n",result[i][IP]);
value = strtok(NULL, s);
strcpy(result[i][PORT], value);
printf("PORT : %s\n",result[i][PORT]);
i++;
}
puts("");
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("%s\n",result[k][j]);
}
}
fclose(fp);
return 0;
}
What you are doing wrong is that you are assigning "value" pointer to elements of "result" array. In your implementation, all the elements of "result" just mirror the value of "value" pointer. Therefore, when you change the value of "value", you also change all the "result" elements.
Because of that, you should use strcpy function after allocating memory for the specific "result" element.
value = strtok(str, s);
result[i][0]=malloc(strlen(value) + 1);
strcpy(result[i][0], value);
When you want to keep-copy strings you have to use the function strcpy()
Instead of result[i][x] = value you should do the following
strcpy(result[i][x], value);
Edit: Before the strcpy you have to use malloc to allocate memory for the result[i][x] string.
eg:
result[i][0] = malloc(10 * sizeof(char));
I suggest using malloc for allocating space for each ip and port, and freeing them at the end with free. Additionally, a struct might be handy here, if you have bigger text files in the future that you want to use.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COLS 2
#define MAXCHAR 10
#define BUFFSIZE 128
void exit_if_null(void *ptr, const char *msg);
int
main(void) {
FILE *filename;
char *result[COLS][MAXCHAR+1];
char buffer[BUFFSIZE];
char *ip, *port;
int row, i = 0;
filename = fopen("ips.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error reading file!\n");
exit(EXIT_FAILURE);
} else {
while (fgets(buffer, BUFFSIZE, filename) != NULL && i < 2) {
ip = strtok(buffer, "-");
port = strtok(NULL, "\n");
result[i][0] = malloc(strlen(ip)+1);
exit_if_null(result[i][0], "Initial Allocation");
result[i][1] = malloc(strlen(port)+1);
exit_if_null(result[i][1], "Initial Allocation");
strcpy(result[i][0], ip);
strcpy(result[i][1], port);
i++;
}
}
for (row = 0; row < i; row++) {
printf("%s\n", result[row][0]);
printf("%s\n", result[row][1]);
free(result[row][0]);
free(result[row][1]);
result[row][0] = NULL;
result[row][1] = NULL;
}
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}