file of strings into array in C - c

I have a file of strings seperated by space and I want to get those strings into an array of defined type but I get an error saying that fscanf doesn't take char**, does anyone know how to do this please?
typedef struct{
char *string;
int name;
} DBZ;
DBZ Table[100];
fp = fopen("text.txt", "r");
if(fp == NULL)
{
fprintf(stderr, "Error opening file.");
exit(1);
}
else {
int i=0;
while(!feof(fp))
{
fscanf(fp,"%s", &Table[i].string);
i++;
}
}

&Table[i].string
You're taking an address of a pointer, which is a pointer-of-a-pointer, which is a char**
Also,
fscanf provides no functionality to allocate the memory you need. You'll have to malloc a block large enough to hold whats in your file. Then you'll want to use something safer than fscanf, preferable the most secure thing available* to make sure you don't overwrite the buffer.
else {
int i=0;
while(!feof(fp))
{
Table[i].string = malloc(100);
fscanf_s(fp,"%s", Table[i].string, 100);
i++;
}
}
* These are Microsoft extensions, your platform may have something different.

You need to allocate space for char *string in your struct. And your %s takes char* not char**

Remove the &, Table[i].string is already a pointer.
string also needs to contain memory. You could change the definition of your struct to:
typedef struct{
char string[90];
int name;
} DBZ;
That assumes that your data will fit in 90 bytes. Depending on what your data is, it could also be a very inefficient way of storing it. malloc(), as others have pointed out, could help you here.

Related

I need to split a file (for now text file) into multiple buffer C

i'm trying to read a file and split this file into multiple buffers.
This is what i came up with:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PKT_SIZE 2048;
#define PATH "directory of some kind"
int main() {
char filepath[200] = PATH;
FILE *packet;
int size = PKT_SIZE;
char *buffer[size];
int i=0;
//OPEN FILE
if((packet = fopen(filepath, "r")) == NULL){ //I'm trying with a txt file, then i'll change it to 'rb'
printf("Error Opening File\n");
return -1;
}
//READ FILE
while(*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet) != NULL) { //read the file and cycling insert the fgets into the buffer i
printf("Create %d buffer\n", i);
i++;
}
fclose(packet);
return 0;
}
Now, when i run this program, i get a SIGSEGV error, i managed to understand that this error is definetly:
*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet) != NULL
Do you have any suggestions?
*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet)
This line as several problems.
buffer[i] is just an un-initialized pointer pointing nowhere.
*buffer[i] is of type char you need to pass the char*.
strlen is not returning the size of the buffer. It is undefined behavior here because you called it over uninitialized pointer value.
Also dererencing whatever fgets is return is bad when the fgets returns NULL. It invokes undefined behavior.
There many solutions to this ranging from dynamic memory allocation to using
char buffer[size][MAXSIZE];. If you go about this you can get input this way:
#define MAXSIZE 100
...
char buffer[size][MAXSIZE];
while(fgets(buffer[i], sizeof(buffer[i]), packet)!=NULL){...
char* buffer[size] is an array of N char* pointers which are uninitialized. You must allocate memory to these before using them or your program will explode in a ball of fire.
The fix is to allocate:
for (size_t i = 0; i < size; ++i) {
buffer[i] = malloc(PKT_SIZE);
}
You're going to be responsible for that memory going forward, too, so don't forget to free later.
Allocating an arbitrary number of buffers is pretty wasteful. It's usually better to use some kind of simple linked-list type structure and append chunks as necessary. This avoids pointless over-allocation of memory.

Stuck on Grabbing a title from a text file

I am attempting to grab a title from a text file in a way that is completely new to me. My code is set up as follows:
struct sequence
{ char *name;
char *sequence;
int sequencelen;
};
int main(int argc, char *argv[])
{
struct sequence *newseq;
getsequence("test.txt", newseq);
}
void getsequence(const char *file, struct sequence *seq)
{
FILE *fp = fopen(file, "r");
struct sequence *seqptr = malloc(sizeof(*seq));
char c;
if (!fp)
{
exit(1);
}
while ((c = fgetc(fp)) != "\n")
{
if (c == '>')
continue;
strcat(seqptr -> name, c);
}
printf("Name: %s", seqptr -> name); //Expected output: this_is_a_new_sequence_title
}
The structure for the text file is as follows:
>this_is_a_new_sequence_title
Using structs in this way is, like I said, new to me, but seeing how it is another way to use them I would like to know how to do it. I am unsure, however, if I'm using them correctly, especially with regards to the strcat function.
Do I have to dynamically allocate memory for the struct's member variables, and, if so, how would I go about doing that? Or do I just have everything horribly wrong?
You're never allocating memory for the string. So when you call strcat(), the destination string is uninitialized memory, leading to undefined behavior.
Also, the 2nd argument to strcat() is a string, not a character. That's more undefined behavior as the library function interprets the single character as the address of a string.
You need to initialize storage space for sequence when you allocate it. Also, for code like this (dynamic strings) it's good to separate "allocated room" from "string length", and store both.

Beginner C : Dynamic memory allocation

Switching to C from Java, and I'm having some troubles grasping memory management
Say I have a function *check_malloc that behaves as such:
// Checks if malloc() succeeds.
void *check_malloc(size_t amount){
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if ( tpt == NULL ){
fprintf(stderr, "No memory of %lu bytes\n", amount);
exit(1);
}
return tpt;
}
I also have the following variables to work with:
FILE *f = fopen("abc.txt", "r"); // Pointer to a file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
}
My goal is to use *check_malloc to dynamically allocate memory so that the String pointed to by *pname is just the correct size for storing "mynamisbob", which is the only thing on the first line of the text file.
Here is my (failed) attempt:
int main(int argc, char *argv[]){
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
char currentline[150]; // Char array for storing current line of file
while(!feof(f)){
fgets(currentline,100,f);
pname = &currentline;
}
But I know this probably isn't the way to go about this, because I need to use my nice check_malloc* function.
Additionally, in my actual text file there is a "<" symbol before the name on the first line.But I just want the *pname to point to a String saying "mynameisbob" without the "<" symbol. This isn't that important now, it just is reinforcement to me that I know I can't just set the pointer to point straight to currentline.
Can anyone help me fix my thinking on this one? Thanks a lot.
In C you need to copy chars, not the "strings" (which are just pointers). Check out strcpy() and strlen(). Use strlen() to determine how long the line actually is which fgets has read, then use your malloc() to allocate exactly that (plus 1 for the 0). Then copy the chars over with strcpy().
There are several problems in your code, see my comments in this example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Checks if malloc() succeeds.
void *check_malloc (size_t amount) {
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if (tpt == NULL) {
fprintf (stderr, "No memory of %lu bytes\n", amount);
exit (EXIT_FAILURE);
}
return tpt;
}
// To avoid subtle errors I have defined buffer size here
#define BUFFER_SIZE 150
// I have used the (void) version of main () here, while not strictly neccessary, you where not using argc and argv anyway, so the can be left out in this case
int main (void) {
// It might be a good idea to make the filename a char[] as well, but I leave that as an exercise to the reader.
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
// You have to check whether the file was *actually openend*
if (f == NULL) {
fprintf (stderr, "Could not open file abc.txt\n"); // '"...%s\n", filename);' might better.
exit (EXIT_FAILURE);
}
char *pname; // Pointer to a string for storing the name
char currentline[BUFFER_SIZE]; // Char array for storing current line of file
while(!feof (f)) {
char *res = fgets (currentline, BUFFER_SIZE, f);
// fgets returns NULL when EOF was encountered before the next '\n'
if (res) {
size_t read = strlen (res);
// The line might have been empty
if (read) {
// Better use "sizeof *varname", while char is always 1 byte it is a good practice
pname = check_malloc ((read + 1) * sizeof *pname); // + 1 because we have to provide an extra char für '\0'
strncpy (pname, currentline, read); // You have to use strcpy or strncpy to copy the contents of the string rather than just assigning the pointer
// What was allocated must be freed again
free (pname);
}
}
}
fclose(f); // Always close everything you open!
return EXIT_SUCCESS;
}
Actually you really don't have to use pname in this simple case, because currentline already contains the line, but since you're trying to learn about memory management this should give you a general idea of how things work.
In your code you had this line:
pname = &currentline;
There are two problems here:
As already mentioned in my code assigning currentline to pname only copies the pointer not the contents.
The correct assignment would be pname = currentline (without the address operator &), because currentline is also a pointer under the hood (it behaves like char *currentline even though it's statically allocated).

Segmentation Fault(core dump)

I am getting Segmentation error(core dump) in the following code:
void Update_Log( )
{
struct logData update;
int file;
char *writeBuffer=NULL;
if((file=creat("/home/user/Desktop/DMS/DMS/filename.txt",O_RDONLY|O_WRONLY))==-1)
perror("file not opened");
update.clientName="user";
update.filename="user";
update.timestamp="some time";
sprintf(writeBuffer,"%s %s %s",update.clientName,update.filename,update.timestamp);
if((write(file,writeBuffer,sizeof(writeBuffer)))==-1)
perror("write unsuccessful");
close(file);
}
My structure is as follows:
struct logData
{
char *clientName;
char *filename;
char *timestamp;
};
Can anyone help in this?
You're trying to write to writeBuffer which is a null pointer, you should declare it as array(1), or allocate a memory on the heap(2) for it.
char writeBuffer[100];
char *writeBuffer=malloc(100)
in both cases you should not use sprintf, but snprintf to make sure you are not overflowing your buffer.
When 'update' is created it only allocates the space for the pointers of the strings clientName, filename, timestamp; it does not allocate space for the string itself. A quick hack would be to do something like update.clientName = (char*)malloc(sizeof(char)*len) where len is the length of what you want to allocate. Then you should really check the return code of that call...
This is exactly the same issue as with the write buffer... you just need to make sure you allocate space for all your strings.
The error is these two lines:
char *writeBuffer=NULL;
/* ... */
sprintf(writeBuffer, /* ... */);
Here you write into a NULL pointer.
Create an array instead, e.g.
char writeBuffer[32];
You need to allocate space for writeBuffer.
You could use malloc, or if you have limits on the size of the data (eg if it will be less than 256 bytes) just declare it as
char writeBuffer[256];
I'd also recommend looking up and using snprintf instead of sprintf to make sure data doesnt run off the end.
your struct store only pointers, no memory is allocated for the actual data.
Either you should have
struct logData
{
char clientName[SOMEDEFINE1NUMBERHERE];
char filename[SOMEDEFINE2NUMBERHERE];
char timestamp[SOMEDEFINE3NUMBERHERE];
};
or you allocate the memory (malloc)
update.clientname = (char *)malloc(SOMEDEFINE1NUMBERHERE);
strncpy(update.clientname, "user");
As Binyamin Sharet wrote sprintf is not allocating the output buffer. The caller must provide an output buffer that is long enough. This is not always simple. Therefor I advise you to use fopen instead of open. Then you can code like that:
void Update_Log( )
{
struct logData update;
FILE *file = fopen("/home/user/Desktop/DMS/DMS/filename.txt", "w");
if(file==NULL) {
perror("file not opened");
return;
}
update.clientName="user";
update.filename="user";
update.timestamp="some time";
if(fprintf(file,"%s %s %s",update.clientName,update.filename,update.timestamp) < 0)
perror("write unsuccessful");
fclose(file);
}
As you can see the code is shorter and it has no potential buffer overflow.
It crashes, because writeBuffer is NULL.
You need to allocate memory for writeBuffer using malloc - use strlen (for example) to calculate the neccesary space (don't forget \0 and the spaces in the sprintf).
OR, you may allocate some fixed size array automatically:
char writeBuffer[ SOME_SIZE_BIG_ENOUGH ];
Also, you should not do this:
update.clientName="user";
update.filename="user";
update.timestamp="some time";
You have several options:
use strcpy
use strdup (POSSIX)
make the pointers const char*, not just char*.

unhandled exception while running the program in VC++ 2008

I was trying to open a binary file in the directory and perform the operations accordingly.I doubt this line..is not the correct way of representation to work the below logic.
int main(int argc, char* argv[])
{
int k=0;
FILE *fp;
unsigned char cd[255];
unsigned long cd1[500];
char *buffer;
unsigned long sa=80044;
int j=0,i=0,n=0;
DIR *dir;
struct dirent *direntry; //could be a file, or a directory
dir = opendir("C:/Documents and Settings/Administrator/Desktop/vicky");
if(!dir) {
printf("Error: directory did not open!\n");
return 1;
}
while((direntry=readdir(dir))!=NULL) {
if(++k < 100)
{
printf("%s\n",direntry->d_name);
sprintf(buffer,"%s",direntry->d_name);//here i got the unhanded exception.
fp=fopen("buffer","rb");
sa=sa-44;
sa=sa/8;
if(fp==NULL)
{
printf("file not found!");
}
else
{
for(j=0;j<(sa);j++)
{
for(i=0;i<8;i++)
{
cd[i]=fgetc(fp);//get each character from file
// printf("%c",cd[i]);
}
if(i==8)//if the i is 8 the character then do the following,just read 8 bytes and then calculate the cd1.
{
sa=sa-8;
cd1[j]=(cd[6] * 65536 + cd[5] * 256 + cd[4]);//multiply the positional weightage and calculate the cd1,which contains the 7 digits decimal value.
//if((cd1[j]> 0x7FFFFF)&&(cd1[j]<=0xFFFFFF))
//cd1[j]=cd1[j]- 0xFFFFFF;
//cd1[j]=cd1[i] * -1;
}
printf("completes first 8 bytes read:%d - %d",j,cd1[j]);//print j and cd1[j] value in console window
}
fclose(fp);//close the file
}
}
if((strcmp(direntry->d_name, "text.txt"))==0) {
printf("\nThe %s file has been found\n",direntry->d_name);
k=-99; //just a flag value to show the file was found
break;
}
}
if(k!=-99)
printf("\nThe test.txt file was not found\n");
closedir(dir);
printf("\n");
getchar();
return 0;
}
This is error i got:Unhandled exception at 0x1029a189 (msvcr90d.dll) in READ_TEXT.exe: 0xC0000005: Access violation writing location 0xcccccccc.Kindly let me any suggestion to read the "direntry->d_name" file name to process the above logic.
Make the character buffer an ordinary array, for simplicity's sake:
char buffer[1024];
That way you're sure to have the memory put aside and ready to use. You should use snprintf() if your platform provides it.
buffer is not allocated. sprintf() is basically attempting to write "nowhere".
The destination variable needs to be either allocated on the heap using malloc or on the stack restricting its use to the current scope.
You have only declared char* buffer, not allocate memory for it using malloc().
Your problem is an uninitialized pointer.
Initialize the pointer with malloc or try an array
char buffer[1024];
change
char * buffer;
to
char buffer[MAX_PATH];
or something similar.
U must allocate the memory for the buffer variable.
char *buffer; statement is not allocating any memory so that i could have
any data.
so better u try
chat buffer[//buffer length];
or char *buffer = new char(//buffer length);
or char buffer = (char)malloc(//buffer length);
these above statement will allocate memory and fix your issue.

Resources