I'm trying to read a file and store its content in a variable, here's my code:
#define _BSD_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
// CEK ROUTER MODEL
char* router_model;
char* model() {
char filename[] = "/tmp/cpuinfo";
char* key = "system type";
char* value;
FILE *file = fopen(filename, "r");
if (file != NULL) {
char line[1000];
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
value += 2;
router_model = strdup(value);
break; // once the key has been found we can stop reading
}
}
fclose(file);
}
else {
perror(filename); //print the error message on stderr.
}
return router_model;
}
// TULIS SERIAL NUMBER KE FILE
char tulis(char p[100]) {
// Write a serial number to a file
char sn[30];
char encrypt_sn[300];
printf("Serial Number:\n");
scanf("%s", sn);
FILE *f = fopen("/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", "w");
if (f == NULL) {
printf("Error opening file!\n");
exit(1);
}
fprintf(f,"Serial Number: %s", sn);
fclose(f);
sprintf(encrypt_sn, "ccrypt -e /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c -K %s", p);
system(encrypt_sn);
system("mv /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c");
printf("Serial number is saved in /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c\n");
return 0;
}
// BACA SERIAL NUMBER & SIMPAN DALAM SEBUAH VARIABLE
char baca(char p[100]) {
// Store the serial number from a file in a variable
char line[50];
char decrypt_sn[300];
char key[30] = "Serial Number";
char *serial_number;
if( access( "/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", F_OK ) != -1 ) {
system("cp /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/");
system("mv /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt");
sprintf(decrypt_sn, "ccrypt -d /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt -K %s", p);
system(decrypt_sn);
FILE *file = fopen("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c", "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
value += 2;
serial_number = strdup(value);
break; // once the key has been found we can stop reading
}
}
fclose(file);
//printf("Your hardware serial number is: (%s)\n", serial_number);
remove("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c");
}
else {
printf("fsn not found\n");
return -1;
}
return 0;
}
int main(int argc, char* argv[]) {
char *r;
char *del;
char *decrypt;
int ret;
char input[30];
char *p;
char *original_sn;
p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
//tulis(p);
original_sn = baca(p);
printf("SN: %s\n", original_sn);
return 0;
}
The file is /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c and the content of that file is Serial Number: 1866203214226041 and original_sn should output 1866203214226041. However when I run that code I get:
test.c: In function ‘main’:
test.c:105:14: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
original_sn = baca(p);
^
SN: (null)
How do I fix it ?
This happens because your baca function returns a char, whereas you are assigning its return value to a char *. Maybe you wanted to use a char variable.
If function baca can change the contents of the memory block pointed by the input argument:
Change this:
char* p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
To this:
char p[] = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
If function baca cannot change the contents of the memory block pointed by the input argument:
Change this:
char baca(char p[])
To this:
char baca(const char* p)
In baca you are allocating initialised memory using strdup:
serial_number = strdup(value);
, then you do nothing with that.
It is clear that you think that the function returns a pointer to that memory so you can print it's content. However, it is not what you are doing. Because all your baca function is doing is returning a value indecating if it sucseede (0) or not (-1). And you are jut ignoring that pointer and leaving some wasted unused memory allocated by your prog.
Their are 2 methodes to fix your code:
Method1 : returning the serial_number
char* baca(const char* p) {
// Store the serial number from a file in a variable
char line[50];
char decrypt_sn[300];
char key[30] = "Serial Number";
char *serial_number=NULL;
if( access( "/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", F_OK ) != -1 ) {
system("cp /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/");
system("mv /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt");
sprintf(decrypt_sn, "ccrypt -d /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt -K %s", p);
system(decrypt_sn);
FILE *file = fopen("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c", "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
if(value!=NULL){/*testing the return value for erros so you prog doesn't cruch*/
value += 2;
serial_number = strdup(value);
}
/*in case off erreor you can choose one of two options:*/
/*optinon1: print an error mesage then kill your prog*/
else{
printf("Error: corrupted file!\n");
exit(1);
}
/*option 2: removing the else part your baca then will return NULL and the calling code should understand that an error has occured*/
break;
}
}
fclose(file);
remove("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c");
}
else {
printf("fsn not found\n");
}
return serial_number;
}
int main(int argc, char* argv[]) {
char *r;
char *del;
char *decrypt;
int ret;
char input[30];
char *p;
char *original_sn;
p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
//tulis(p);
original_sn = baca(p);
if(original_sn!=NULL){
printf("SN: %s\n", original_sn);
free(original_sn);/*you should free the memory allocated by strdup once you are done using it.*/
}
else{
printf("An error has occured\n");
}
return 0;
}
Method2 : pass by reference
char baca(const char* p, char **serial_number) {
// Store the serial number from a file in a variable
char line[50];
char decrypt_sn[300];
char key[30] = "Serial Number";
char ret = 0;/*the return value 0 means no error.*/
if( access( "/tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c", F_OK ) != -1 ) {
system("cp /tmp/halo/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/");
system("mv /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt");
sprintf(decrypt_sn, "ccrypt -d /tmp/fsn-55cfc8770b69cc07268fae7f25ee444c.cpt -K %s", p);
system(decrypt_sn);
FILE *file = fopen("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c", "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
while (fgets(line, sizeof line, file) != NULL) /* read a line from a file */ {
//fprintf(stdout, "%s", line); //print the file contents on stdout.
if (strncmp(line, key, strlen(key)) == 0) {
char* value = strchr(line, ':');
if(value!=NULL){/*testing the return value for erros so you prog doesn't cruch*/
value += 2;
*serial_number = strdup(value);
}
/*in case off erreor you can choose one of two options:*/
else{
/*optinon1: print an error mesage then kill your prog*/
/*option 2: making the return value non 0 and the calling code should understand that an error has occured*/
#define OPTION1
#ifdef OPTION1
printf("Error: corrupted file!\n");
exit(1);
#else
ret=-2; //to used this option comment out #define OPTION1
#endif
}
break;
}
}
fclose(file);
remove("/tmp/fsn-55cfc8770b69cc07268fae7f25ee444c");
}
else {
printf("fsn not found\n");
ret=-1;
}
return ret;
}
int main(int argc, char* argv[]) {
char *r;
char *del;
char *decrypt;
int ret;
char input[30];
char *p;
char *original_sn=NULL;
p = "MmI4MTUxM2FjMjRlMDkzYmRkZGQyMjcwMjQ4OWY3MDAwNGZiYTM0MWNkZGIxNTdlYzAxN2";
//tulis(p);
switch(baca(p,&original_sn))
{
case 0: //evrything is fine
printf("SN: %s\n", original_sn);
free(original_sn);
break;
case -1:/* handle each error as you should*/
case -2:
default:
printf("An error has occured\n");
}
return 0;
}
Hope this helps. :).
Related
I'm reading file using fread().[read file only]
On compilation, the compiler throws a "Segmentation fault (core dumped)" error.
I'm using structure.
I wrote this code.
type #include <string.h>
#include <stdio.h>
#include <stdlib.h>
int twilio_send_functionapi(char *channel, char *status); // function declartion
struct credentials
{
char *account_sid;
char *auth_token;
char *from_number;
char *to_number;
} c1;
int main(int argc, char *argv[])
{
FILE *fp;
struct credentials input;
fp = fopen("data.config", "r");
if (fp == NULL)
{
printf("Error\n");
return -1;
}
dentials.to_number = (char*)malloc(sizeof(char)*100);
while(fread(&c1,sizeof(struct credentials),1 ,fp))
fscanf(fp,"%s %s %s %s", c1.account_sid, c1.auth_token,c1.from_number, c1.to_number);
char *channel,*status;
channel = argv[1];
status = argv[2];
twilio_send_functionapi(channel,status); //function call
}
Don't know where I'm mistaken.
here is .conf file which needs to be read
account_sid : AC40cfb4f3e98b55b13a9b93527683171e
auth_token : 5f6906d7847ad1fc1fc1170ab60e40fd
from_number : 15867854760
to_number : 1212321123
Instead of fread(), fscanf(), use fgets() to read a line of the file into a string.
// 123456789 123456789 123456789 123456789
//account_sid : AC40cfb4f3e98b55b13a9b93527683171e
#define SID_LEN 34
struct credentials {
char account_sid[SID_LEN + 1]; // Use array here, not pointer.
// ... omitted for brevity
} c1;
#define LINE_SIZE 100
char line[LINE_SIZE];
if (fgets(line, sizeof line, fp)) {
if (sscanf(line, "account_sid : %34s", c1.account_sid) == 1) {
; // Success
} else {
; // Failed
}
Continue likewise for the other c1 members`.
Thank you everyone.
I resolve my problem.
char credential[4][100] ;
int main()
{
FILE *fp;
fp = fopen("data.config", "r");
if (fp == NULL)
{
printf("Error\n");
return -1;
}
printf("File is opened\n");
if ((fscanf(fp,"account_sid-%s\n",credential[0])!= 1))
{
printf("error reading account_sid value\n");
return -1;
}
fclose(fp);
}
This is a program to remove particular lines in a file. It copies the lines which are needed and prints it in another file in the same directory. I'm not getting any errors except for warnings such as incompatible pointer type [-Wincompatible-pointer-types]. When I run the code I also get the prtintf statement but when entered input Segmentation fault (core dumped). Is it related to the warnings or is it something else ?
code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include <ctype.h>
char *name_find(char *buf[], char *name[]) {
const char *p = NULL;
size_t len = strlen(name);
if (len > 0) {
for (p = buf ; (p = strstr(p, name)) != NULL; p++) {
if (p == buf || !isalnum((unsigned char)p[-1])) {
if (!isalnum((unsigned char)p[len]))
break; /* we have a match! */
p += len; /* next match is at least len+1 bytes away */
}
}
}
return p;
}
int main()
{
char name[25];
char buf[100];
setenv("PFILE","/home/ashwin/Desktop/FILE/",1);
char ori_path[100],new_path[100];
if (!getenv("PFILE")){
}
else{
strcpy(ori_path, getenv("PFILE"));
strcpy(new_path, getenv("PFILE"));
strcat(ori_path, "shadow");
strcat(new_path, "shadow1");
}
bool success=false;
printf("Enter the command\n ");
printf("userdel ");
FILE *fold = fopen(ori_path, "r"); // old file
FILE *fnew = fopen(new_path, "w"); // new temp file
fgets(name,25,stdin);
for(int i = 0; i < strlen(name); i++)
{
if(name[i] == '\n')
{
name[i] = '\0';
break;
}
}
while (fgets(buf, 100, fold)) {
// read lines until error or EOF
if (!name_find(buf, name)) {
fprintf(fnew, "%s", buf);
success=true;
}
}
if(success){
printf("Success !!!\n");
}
return 0;
}
char *name_find(char *buf[], char *name[])
You use char *buf[], which means buf is an array of pointers to char, not a pointer to char. Use char* buf instead. Same goes for name.
Additionally:
FILE *fold = fopen(ori_path, "r"); // old file
FILE *fnew = fopen(new_path, "w"); // new temp file
You should check if the opening of the streams to the files were successful by checking the returned pointers for a null pointer:
FILE *fold = fopen(ori_path, "r"); // old file
if(!fold)
{
fputs("Error at opening fold!", stderr);
exit(1);
}
FILE *fnew = fopen(new_path, "w"); // new temp file
if(!fnew)
{
fputs("Error at opening fnew!", stderr);
exit(1);
}
Try this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
char *name_find(char *buf, char *name) {
const char *p = NULL;
size_t len = strlen(name);
if (len > 0) {
for (p = buf ; (p = strstr(p, name)) != NULL; p++) {
if (p == buf || !isalnum((unsigned char)p[-1])) {
if (!isalnum((unsigned char)p[len]))
break; /* we have a match! */
p += len; /* next match is at least len+1 bytes away */
}
}
}
return p;
}
int main (void)
{
char name[25];
char buf[100];
setenv("PFILE","/home/ashwin/Desktop/FILE/",1);
char ori_path[100],new_path[100];
if (!getenv("PFILE")){
}
else{
strcpy(ori_path, getenv("PFILE"));
strcpy(new_path, getenv("PFILE"));
strcat(ori_path, "shadow");
strcat(new_path, "shadow1");
}
bool success=false;
printf("Enter the command\n ");
printf("userdel ");
FILE *fold = fopen(ori_path, "r"); // old file
if(!fold)
{
fputs("Error at opening fold!", stderr);
exit(1);
}
FILE *fnew = fopen(new_path, "w"); // new temp file
if(!fnew)
{
fputs("Error at opening fnew!", stderr);
exit(1);
}
fgets(name,25,stdin);
for(unsigned int i = 0; i < strlen(name); i++)
{
if(name[i] == '\n')
{
name[i] = '\0';
break;
}
}
while (fgets(buf, 100, fold)) {
// read lines until error or EOF
if (!name_find(buf, name)) {
fprintf(fnew, "%s", buf);
success=true;
}
}
if(success){
printf("Success !!!\n");
}
return 0;
}
The programm should be able to open a file like myFile.txt,
alltough it's real name is myFile without the extension .txt.
So I wrote the function called removeFileExtension() in order
to achieve that.
It does open my file by copying the string from text into filename:
strcpy(filename,text);
FILE *fp = fopen(filename, "r");
So I tried to check what the difference between text and my processed
string from removeFileExtension is.
To check if it even works I mate a function called strComparison(),
which returns either 0 when it is qual or 1 if unequal.
The thing is, after removing the file extension, it shows that both strings
are qual, but I am still not able to open the file.
When I type in ./a.out myFile.txt my comparison function returns 0,
it is equal, but fopen() still is not able to open the file,
respectively I allways get a Segmentation fault.
Does anyone see the problem here?
Why am I getting a Segmentation fault?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void removeFileExtension(char *haystack);
int strComparison(char *one, char *two);
int main(int argc, char const *argv[])
{
//----------------------------------------------------------------------------
// CHECK INPUT VALIDITY
//
if (argc != 2)
{
printf("Usage: ./ass2 [file-name]\n");
return 1;
}
//----------------------------------------------------------------------------
// OPEN FILE (INITIAL)
//
char filename[32];
strcpy(filename, argv[1]);
FILE *fp = fopen(filename, "r"); //FOPEN
//FILE *fp = fopen("start_of_story\0txt", "r"); // this way does work
if (fp == NULL)
{
// IF NOT FOUND: REMOVE EXTENSION
removeFileExtension(filename);
char text[] = "myFile\0";
int ret_val = -1;
ret_val = strComparison(filename, text);
if (ret_val == 0)
printf("[DEBUG] equal\n");
else
printf("[DEBUG] unequal\n");
printf("[DEBUG] ret_val: %d\n", ret_val);
printf("[DEBUG] '%s'\n", filename);
FILE *fp = fopen(filename, "r"); //FOPEN
// IF STILL DOESN'T WORK: ERROR
if (fp == NULL)
{
printf("[ERR] Could not read file %s.\n", filename);
return 3;
}
}
//--------------------------------------------------------------------------
// READ DATA (INITIAL)
//
int bufsize = 1024;
char *buffer = malloc(bufsize * sizeof(char)); //MALLOC
if (!buffer)
{
printf("[ERR] Out of memory.\n");
return 2;
}
fseek(fp, 0, SEEK_SET);
fread(buffer, bufsize, 1, fp);
printf("[DEBUG] %s\n", buffer);
fclose(fp); //FCLOSE
free(buffer);
buffer = NULL;
return 0;
}
void removeFileExtension(char *haystack)
{
char needle[1] = ".";
char *retp; // return pointer
retp = strstr(haystack,needle);
if (*retp == '.')
{
while (*retp != '\0')
{
*retp++ = '\0';
}
printf("[DEBUG] %s\n", haystack);
}
}
int strComparison(char *one, char *two)
{
do
{
printf("[DEBUG] '%c' == '%c'\n", *one, *two);
if (*one++ != *two++)
{
return 1; // return 1 if unqual
}
}
while ( (*one != '\0') || (*two != '\0') );
return 0; // return 0 if qual
}
Resulting output:
user#host ~/Desktop $ ./a.out myFile.txt
[DEBUG] myFile
[DEBUG] 'm' == 'm'
[DEBUG] 'y' == 'y'
[DEBUG] 'F' == 'F'
[DEBUG] 'i' == 'i'
[DEBUG] 'l' == 'l'
[DEBUG] 'e' == 'e'
[DEBUG] equal
[DEBUG] ret_val: 0
[DEBUG] 'myFile'
[ERR] Could not read file myFile.
user#host ~/Desktop $
Quoting C11, chapter 7.24.5.7
char *strstr(const char *s1, const char *s2);
The strstr function locates the first occurrence in the string pointed to by s1 of the
sequence of characters (excluding the terminating null character) in the string pointed to
by s2.
So, both the arguments passed to strstr has to be strings. In your case,
char needle[1] = ".";
is not a string. You did not allow the space for the null-terminator. Either use
char needle[2] = ".";, at least, or,
char needle[ ] = ".";, or,
char const* needle = ".";
As a side effect, whenever the call to removeFileExtension() is reached, you'll face with undefined behavior
That said, beware!!
You are doing something like
retp = strstr(haystack,needle);
if (*retp == '.')
i.e., dereferencing the returned pointer from strstr(). If, strstr() returns a NULL pointer, you'll again be trapped in UB.
EDIT:
For those who still has confusion about string, check definition in chapter §7.1.1 (emphasis mine)
A string is a contiguous sequence of characters terminated by and including the first null
character. [...]
At least I found the problem:
After removing the file's extension, I am still
trying to open the old file pointer fp, which
gave me the NULL-pointer back. The new file pointer
inside the body of the if(fp == NULL){...} only
exists inside the scope of the if-statement.
So I created a test_pointer, which first looks if
the file even exists, if not, he removes the extension.
Than I try again to open the file, this time with fp.
Thanks to everybody for the hints, especially to
Sourav Ghosh
for your improvement suggestions!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int removeFileExtension(char *haystack);
int main(int argc, char const *argv[])
{
char filename[64];
strcpy(filename, argv[1]);
//----------------------------------------------------------------------------
// CHECK INPUT VALIDITY
//
if (argc != 2)
{
printf("Usage: ./ass2 [file-name]\n");
return 1;
}
//----------------------------------------------------------------------------
// CHECK FILE EXISTENSE
//
FILE *test_pointer = fopen(filename, "r"); //FOPEN
if (test_pointer == NULL) // if not found: remove extension
{
int ret_val = removeFileExtension(filename);
if (ret_val == -1)
{
printf("[ERR] Could not remove file extension.\n");
return 3;
}
}
//----------------------------------------------------------------------------
// OPEN FILE (INITIAL)
//
FILE *fp = fopen(filename, "r"); //FOPEN
if (fp == NULL) // if still doesn't work: error
{
printf("[ERR] Could not read file %s.\n", filename);
return 3;
}
//----------------------------------------------------------------------------
// READ DATA (INITIAL)
//
int bufsize = 1024;
char *buffer = malloc(bufsize * sizeof(char)); //MALLOC
if (!buffer)
{
printf("[ERR] Out of memory.\n");
return 2;
}
fseek(fp, 0, SEEK_SET);
fread(buffer, bufsize, 1, fp);
fclose(fp); //FCLOSE
printf("[DEBUG] %s\n", buffer);
free(buffer); //FREE
buffer = NULL;
return 0;
}
int removeFileExtension(char *haystack)
{
char needle[] = ".";
char *retp; // return pointer
retp = strstr(haystack,needle);
if(!retp) // to prevent UB
return -1;
if (*retp == '.')
{
while (*retp != '\0')
{
*retp++ = '\0';
}
printf("[DEBUG] %s\n", haystack);
}
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
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.
I have looked for an answer to my question for almost two days and tried every solution suggested to no avail.
I am trying to access a file through a linux terminal using my C Program.
I want to run popen() to do this.
The command I want to run in popen() is : grep -o %s /usr/share/dict/words
Where %s is a variable word that changes each iteration. I have tried using pointers, arrays, and alternative functions such as asprintf() / snprintf()
Here is the code I have right now:
char *message = (char *)malloc(500);
strcpy(message, "grep -n");
printf("%s", message);
strcat(message, "hello");
printf("%s", message);
strcat(message, " /usr/share/dict/words"); // SEG FAULT OCCURS HERE
printf("%s", message);
I would then pass this to popen.
I have also tried initializing as: char message[500] and this returns the same error in the same spot.
Here is my full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "caeserheader.h"
int main( int argc, char *argv[]){
char *inputfile;
int n = 0;
int shiftamount = 0;
//Determine amount of arguments
if(argc == 2){
inputfile = argv[1];
}
else if(argc == 3){
inputfile = argv[1];
n = atoi(argv[2]);
shiftamount = n * (-1) ;
}
else{
printf("Please enter a proper number of arguments.");
return -1;
}
//OPENS INPUT FILE
FILE *input = fopen(inputfile, "r");
if(input == NULL){
printf("\n FILE NOT FOUND.");
perror("fopen");
return -1;
}
//RESERVES MEMORY AND GRABS STRING
fseek(input, 0L, SEEK_END);
long Tsize = ftell(input);
rewind(input);
char *inputtext;
inputtext = calloc( 1, Tsize+1);
//ERROR CHECKING
if(!inputtext){
fclose(input), printf("MEMORY FAILED.");
}
if(1!=fread( inputtext, Tsize, 1, input)){
fclose(input), free(inputtext), printf("READ FAIL.");
}
//CREATES DECRYPTED STRING
char newletter;
char *newstring;
int i;
//WITH GIVEN NUMBER OF SHIFTS
if(argc == 3){
newstring = malloc(Tsize + 1);
for(i=0; i<Tsize; i++){
newletter = shift(inputtext[i], shiftamount);
newstring[i] = newletter;
}
}
//WITHOUT GIVEN NUMBER OF SHIFTS
if(argc == 2){
char *message = (char *)malloc(500); //SEG FAULT SOMEWHERE HERE?
// strcpy(message, "grep -n");
// printf("%s", message);
//strcat(message, "hello");
// printf("%s", message);
// strcat(message, "/usr/share/dict/words");
//printf("%s", message);
// word = strtok(inputtext," ,.-!?\n");
// int i;
//for(i=0; i<10; i++){
//word = strtok(NULL," ,.-!?\n");
//printf("\n%s", word);
//}
// if(( fp = popen(message, "r")) == NULL){
//perror("No file stream found.");
//return -1;
// }
// else {
// pclose(fp);
// printf("FOUND.");
// }
}
// PUTS DECRYPTED STRING IN NEW FILE
char copiedname[100];
strcpy(copiedname, inputfile);
strcat(copiedname, ".dec");
FILE *newfile = fopen(copiedname, "w");
fputs(newstring, newfile);
// free(newstring);
fclose(input);
fclose(newfile);
return 0;
}
You have set inputfile to argv[1] and later you have used strcat to append to it. Don't do this. You don't own argv.
The strcat function appends a copy of the source string to the destination string, and then returns a pointer to the destination string. It does not "add two strings and return the result" which is how you seem to be using it.