Issues with structs in C - c

I have an array in a struct. I'm reading from a file into a string. I use strtok to get the first few characters, and i want to pass the rest of the line into the struct, to eventually be passed into a thread. I'm getting the following error:
incompatible types when assigning to type char[1024] from type char *
Referring to the line indicated below with the comments. It probably has to do with how i'm trying to copy character arrays, but i'm not sure on a better way.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <linux/input.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
typedef struct
{
int period; //stores the total period of the thread
int priority; // stores the priority
char pline[1024]; // stores entire line of text to be sorted in function.
}PeriodicThreadContents;
int main(int argc, char* argv[])
{
//opening file, and testing for success
//file must be in test folder
FILE *fp;
fp = fopen("../test/Input.txt", "r");
if (fp == NULL)
{
fprintf(stderr, "Can't open input file in.list!\n");
exit(1);
}
char line[1024];
fgets(line, sizeof(line), fp);
//getting first line of text, containing
char *task_count_read = strtok(line," /n");
char *duration_read = strtok(NULL, " /n");
//converting char's to integers
int task_count = atoi(task_count_read);
int i = 0;
PeriodicThreadContents pcontents;
printf("started threads \n");
while (i < task_count)
{
fgets(line, sizeof (line), fp);
strtok(line," ");
if (line[0] == 'P')
{
char *period_read = strtok(NULL, " ");
pcontents.period = atoi(period_read);
printf("%d",pcontents.period);
printf("\n");
char *priority_read = strtok(NULL, " ");
pcontents.priority = atoi(priority_read);
printf("%d",pcontents.priority);
printf("\n");
printf("\n%s",line);
memcpy(&(pcontents.pline[0]),&line,1024);
printf("%s",pcontents.pline);
}
}
return 0;
}

C cannot handle strings as other languages do. C doesn't have string assignments or comparisons without using auxiliary functions.
In order to copy a string in a buffer you can use:
strcpy(pcontents.pline, line);
Or even (to have a warranty that your string is not longer than 1024 bytes):
memcpy(pcontents.pline, line, 1024);
pcontents.pline[1023] = '\0';
For other string operations check: http://www.gnu.org/software/libc/manual/html_node/String-and-Array-Utilities.html#String-and-Array-Utilities

You need to copy the chars from the buffer into pcontents.pline (assuming pcontents is a PeriodicThreadContents).

strcpy(pcontents.pline, strtok(NULL, " "));

Related

Copy lines from file to char *array[]?

Hi need a little bit of help here. I have a file with 5 lines and I want to put this lines into an array of type char *lines[5]; but I can't figure it out why the following isn't working.
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fp = fopen("name.txt", "r");
char *str;
char *list[5];
int i = 0;
while (fgets(str, 100, fp) != NULL) // read line of text
{
printf("%s", str);
strcpy(list[i], str);
i++;
}
}
As the commenters stated, you need to create an array (which is nothing more than a space in the memory) of a sufficient size to store your string. One approach to solve your problems is the following, note the comments:
#include <stdio.h>
#include <string.h>
int lines(FILE *file); //try to format the code according to some standard
int main(void) {
FILE *fp = fopen("name.txt", "r");
char list[5][100]; //make sure you allocate enough space for your message
// for loop is more elegant than while loop in this case,
// as you have an index which increases anyway.
// also, you can make sure that files with more than 5 lines
// do not break your program.
for(int i = 0; i<5 ;++i )
{
if(fgets(list[i], 100, fp) == NULL){
break;
}
//list[i] is already a string, you don't need an extra copy
printf("%s", list[i]);
}
}

Read a file specified as an argument and return its' lines

I have an exercise in which I have to read a file containing strings and I have to return the content using one/multiple arrays (this is because the second part of this exercise asks for these lines to be reversed, I'm having problems - and therefore ask for help - with the input).
So far, I have this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 1024
int main(int argc, char *argv[]){
char* input[LENGTH];
if(argc==2){
FILE *fp = fopen(argv[1], "rt");
if(fp!=NULL){
int i=0;
while(fgets(input, sizeof(input), fp)!=NULL){
input[i] = (char*)malloc(sizeof(char) * (LENGTH));
fgets(input, sizeof(input), fp);
i++;
}
printf("%s", *input);
free(input);
}
else{
printf("File opening unsuccessful!");
}
}
else{
printf("Enter an argument.");
}
return 0;
}
I also have to check whether or not memory allocation has failed. This program in its' current form returns nothing when run from the command line.
EDIT: I think it's important to mention that I get a number of warnings:
passing argument 1 of 'fgets' from incompatible pointer type [-Wincompatible-pointer-types]|
attempt to free a non-heap object 'input' [-Wfree-nonheap-object]|
EDIT 2:
Example of input:
These
are
strings
... and the expected output:
esehT
era
sgnirts
In the exercise, it's specified that the maximum length of a line is 1024 characters.
You probably want something like this.
Comments are in the code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 1024
int main(int argc, char* argv[]) {
if (argc == 2) {
FILE* fp = fopen(argv[1], "rt");
if (fp != NULL) {
char** lines = NULL; // pointer to pointers to lines read
int nboflines = 0; // total number of lines read
char input[LENGTH]; // temporary input buffer
while (fgets(input, sizeof(input), fp) != NULL) {
char* newline = malloc(strlen(input) + 1); // allocate memory for line (+1 for null terminator)
strcpy(newline, input); // copy line just read
newline[strcspn(newline, "\n")] = 0; // remove \n if any
nboflines++; // one more line
lines = realloc(lines, nboflines * sizeof(char*)); // reallocate memory for one more line
lines[nboflines - 1] = newline; // store the pointer to the line
}
fclose(fp);
for (int i = 0; i < nboflines; i++) // print the lins we've read
{
printf("%s\n", lines[i]);
}
}
else {
printf("File opening unsuccessful!");
}
}
else {
printf("Enter an argument.");
}
return 0;
}
Explanation about removing the \n left by fgets: Removing trailing newline character from fgets() input
Disclaimers:
there is no error checking for the memory allocation functions
memory is not freed. This is left as an exercise.
the way realloc is used here is not very efficient.
you still need to write the code that reverses each line and displays it.
You probably should decompose this into different functions:
a function that reads the file and returns the pointer to the lines and the number of lines read,
a function that displays the lines read
a function that reverses one line (to be written)
a function that reverses all lines (to be written)
This is left as an exercise.

Trying to read a two numbers from a text file

I am trying to read two numbers from a text file. I used strtok, and the delimiter is " ". The text file (named data.txt) file has only two numbers, the line is "3 5". But the program crashes... any help is appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
FILE *data;
data = fopen("data.txt", "r");
int m, n;
char *line, *number;
while(!feof(data))
{
fscanf(data, "%s", line);
number = strtok(line, " ");
m = atoi(number);
number = strtok(NULL, " ");
n = atoi(number);
}
}
line is a uninitialized pointer, it doesn't point to any valid memory location so you can't use it to store data, use an array instead.
while(!feof(data)) is not what you'd want to use to control your read cycle.
Use fgets/sscanf to parse the values, simple and easy way to do it:
FILE *data;
data = fopen("data.txt", "r");
int m, n;
char line[32];
if (data != NULL)
{
while (fgets(line, sizeof line, data)) // assuming that you want to have more lines
{
if(sscanf(line, "%d%d", &m, &n) != 2){
// values not parsed correctly
//handle parsing error
}
}
}
Or as #chux pointed out, to detect extra junk on the line:
char end;
if(sscanf(line, "%d%d %c", &m, &n, &end) != 2) {
// if more characters exist on the line
// the return value of sscanf will be 3
}
If the values in the file can be outside the range of an int consider using strtol instead of sscanf.

strstr() causing a segmentation fault error

The objective here is to take a whole text file that I dump into a buffer and then use the strcasestr() function to find the pointer of the word I am looking for within my buffer. It constantly gives me the segmentation fault error. At first, I thought it may be size so I tried with smaller sizes but it doesn't work either. The function only works with strings I create inside the actual code (ex : char * bob = "bob"; char * bobsentence = "bob is cool"; strstr(bobsentence, bob);). Which leads me to believe it has something to do with the fgets(). Any help is appreciated, really stuck on this one.
#define _GNU_SOURCE //to use strcasestr
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void textEdit(char *path, char *word){
printf("%s\n", path);
FILE *textFile;
//FILE *locationFile;
//FILE *tempFile;
char counter[1024];
int count = 0;
textFile = fopen(path, "r+");
//locationFile = fopen(path, "r+");
//opens file to read and write and opens temp file to write
if( textFile == NULL){ //|| tempFile == NULL || locationFile == NULL) ) {
printf ("\nerror\n");
return;
}
// SECTION : ALLOCATES MEMORY NEEDED FOR COPY TEXT IN ARRAY
// finds number of lines to estimate total size of array needed for buffer
while((fgets(counter, sizeof(counter), textFile)) != NULL){
count++;
}
fclose(textFile);
FILE *tempFile = fopen(path, "r+");
count *= 1024;
printf("%d %zu\n",count, sizeof(char));
char *buffer = malloc(count); //1024 is the max number of characters per line in a traditional txt
if(buffer == NULL){ //error with malloc
return;
}
// SECTION : DUMPS TEXT INTO ARRAY
if(fgets(buffer, count, tempFile) == NULL){
printf("error");
} //dumps all text into array
printf("%s\n", buffer);
char * searchedWord;
while((searchedWord = strcasestr(buffer, word)) != NULL){
}
fclose(tempFile);
//fclose(locationFile);
free(buffer);
}
It looks that you forgot to initialize count variable to 0:
int count = 0;
You increment it and it can contain any random value, even negative.
Also, note that your utilization of strstr doesn't look correct. The function returns the pointer to first occurrence that matches. Note, that it doesn't remember already found matches, so if match exists it should loop forever in this loop. Instead it should look like:
char *pos = buffer;
while((pos = strcasestr(pos, word)) != NULL){
searchedWord = pos;
/* do something with searchedWord but remember that it belongs to
allocated buffer and can't be used after free() */
pos++;
}

Reading from a text file that contains a list

The purpose of the program is to read a text file that contains a list of 55 authors and titles of books. The format of the list goes (author name, booktitle). I can use malloc, strlen, strtok, and strcopy. So far I got the program to read out the names of the authors but I am stuck on how to get the program to read the titles of the books.How would I get the program to read the titles of the books from the text file? I know that there are errors in this code so please be kind .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void loadBookName(char* filename, char* authorName[55], char* bookName[55]);
int main(int argc, char* argv[])
{
//Create two arrays each with length 55
char* authorName[55];
char* bookName[55];
//Ask the user for the name of the file
char fileName[30];
//Insert your code here
printf("Please enter the name of the file\n");
scanf("%s", fileName);
//Call the method loadBookName
loadBookName(fileName, authorName, bookName);
return 0;
//Print the two arrays to test if the two arrays were correctly loaded with the data
int i = 0;
printf("%-30s%-40s\n", "Author", "Book");
for (i = 0; i < 55; i++) {
printf("%-30s%-40s\n", authorName[i], bookName[i]);
}
}
/*
loadBookName method
This method is responsible for:
1. Take a file containing a book name and the author name as input
2. Open the file
3. Read the information in the file and store it in two arrays: authorName, bookName
4. Return the two arrays to the main method.
*/
void loadBookName(char* filename, char* authorName[55], char* bookName[55])
{
int i;
char string_array[80];
const char comma[2] = ",";
//Open the file
FILE *fp;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("Failed to open file\n");
exit(1);
}
for (i=0; i<55; i++)
{
fgets(string_array, 80, fp);
authorName[i] = strtok(string_array, comma);
printf("%s\n", *authorName);
}
//Close the file
fclose(fp);
}
when I run the program in terminal it asks me to enter the filename (books.txt). Then when I enter the file name, the program prints a list of 55 authors.
I don't have a compiler in front of me, so excuse the compilation error if it has any. But I think you can try something as below, within your existing code:
UPDATED:
After comments, I've updated one line. This is compiled and working.
Assumptions: User need to take care of error-handling e.g. file not present, file unable to open, buffer overflows etc.
char *token;
for (i=0; i<55; i++)
{
//fgets(string_array, 80, fp);
//This will take care in case if lines are less than 55
if(!fgets(string_array, 80, fp))
break;
//Get the author
token = strtokstring_array, comma);
authorName[i] = token; // or use string copy functions
//Get book name
while( token != NULL )
{
printf( " %s\n", token ); //this shall print author name
token = strtok(NULL, comma);
bookName[i] = token;
printf( " %s\n", token ); //this shall print book name
//EDIT: This is additional line after suggestions
token = strtok(NULL, comma);
}
}
Simple way of separating strings with strlcpy:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void )
{
size_t i = 1;
char *authorName, *bookName;
const char *a_line_in_a_file =
"Lewis Carroll,The Hunting of the Snark";
const char *title = a_line_in_a_file;
while ( *title != ','){
title++;
i++;}
authorName = malloc(i);
bookName = malloc(strlen(title));
title++;
#if __BSD_VISIBLE
strlcpy(bookName, title, strlen(title) + 1);
strlcpy(authorName, a_line_in_a_file, i);
#else
snprintf(bookName, strlen(title) + 1, "%s", title);
snprintf(authorName, i, "%s", a_line_in_a_file);
#endif
printf("%-30s%-40s\n", authorName, bookName);
free(authorName);
free(bookName);
return 0;
}

Resources