Error trying to edit character string inside struct string - arrays

My program contains the next structure:
typedef struct user {
char username[LENGTH_USERNAME];
} User
and I have an array inside my main function of struct user
User user_database[NUMBER_USERS];
The problem is that when I pass this database to a function to edit the username field of all the struct user in the array like this:
void initialize_empty_user_database(User database[])
{
int i;
for(i = 0; i < NUMBER_USERS; ++i)
database[i].username[0] = '\0';
}
when trying to compile, I get the next error:
error: incompatible types when assigning to type ‘User’ {aka ‘struct user’} from type ‘char *’
Here is the complete code:
#include <stdio.h>
#include <string.h>
#define LENGTH_USERNAME 21
#define LENGTH_ACTIVITY_NAME 21
#define LENGTH_TASK_DESCR 51
#define NUMBER_USERS 50
#define NUMBER_ACTIVITIES 10
#define NUMBER_TASKS 10000
typedef struct user {
char username[LENGTH_USERNAME];
/* username cannot contain blank characters */
} User;
typedef struct activity {
char name[LENGTH_ACTIVITY_NAME];
/* name cannot contain lowercase letters */
} Activity;
typedef struct task {
int id;
char des[LENGTH_TASK_DESCR]; /* description */
User username[LENGTH_USERNAME];
Activity activity[LENGTH_ACTIVITY_NAME];
int etc; /* Estimated Time of Completion */
int start_time;
} Task;
void initialize_empty_user_database(User database[])
{
int i;
for(i = 0; i < NUMBER_USERS; ++i)
database[i].username[0] = '\0';
}
void initialize_empty_activity_database(Activity database[])
{
int i;
for(i = 0; i < NUMBER_ACTIVITIES; ++i)
database[i].name[0] = '\0';
}
void initialize_empty_task_database(Task database[])
{
int i;
for(i = 0; i < NUMBER_TASKS; ++i) {
database[i].id = -1; /* id == -1 -> task not initialized */
}
}
void read_task_descr(char target[])
{
int i;
char c;
c = getchar();
for(i = 0; i < (LENGTH_TASK_DESCR - 1) || c == '\n'; ++i){
target[i] = c;
c = getchar();
}
target[i] = '\0';
}
int available_tasks(Task database[])
{
int i;
for(i = 0; i < NUMBER_TASKS; ++i) {
if(database[i].id == -1)
return NUMBER_TASKS - i;
}
return 0;
}
int duplicate_descr(Task database[], char descr[])
{
int i;
for(i = 0; i < NUMBER_TASKS; ++i) {
if (strcmp(database[i].des, descr) == 0)
return 1;
}
return 0;
}
int t_exceptions(Task task_database[], char task_descr[])
{
if (available_tasks(task_database) == 0) {
printf("too many tasks");
return 1;
}
else if (duplicate_descr(task_database, task_descr) == 1) {
printf("duplicate description");
return 2;
}
return 0;
}
void new_task(Task database[], int etc, char descr[])
{
static int i = 0;
database[i].id = i + 1; /* id */
strcpy(database[i].des, descr); /* descr */
database[i].username[0] = '\0'; /* username (not attributed) */
strcpy(database[i].activity.name, "TO DO"); /* activity */
database[i].etc = etc; /* estimated time for completion */
database[i].start_time = 0; /* start time (not started) */
++i;
}
int main()
{
/* Database declarations */
User user_database[NUMBER_USERS];
Activity activity_database[NUMBER_ACTIVITIES] = {{"TO DO"}, {"IN PROGRESS"}, {"DONE"}};
Task task_database[NUMBER_TASKS];
/* Variable and array definition */
int time;
int etc; /* estimated time of completion */
char task_descr[LENGTH_TASK_DESCR];
char activity_name[LENGTH_ACTIVITY_NAME];
char username[LENGTH_USERNAME];
/* Auxiliary variables */
char command;
/* Database initilizations */
initialize_empty_user_database(user_database);
initialize_empty_activity_database(activity_database);
initialize_empty_task_database(task_database);
while(1) {
command = getchar();
switch(command) {
case 'q':
return 0;
case 't':
scanf("%d", &etc);
getchar(); /* Consume space separating arguments */
read_task_descr(task_descr);
if(t_exceptions(task_database, task_descr) == 0)
new_task(task_database, etc, task_descr);
break;
default:
printf("Exception: Unknown command\n");
}
getchar(); /* Consume the newline character */
}
return -1;
}
can somebody explain to me what am I doing wrong?
Thanks!
Errors in the original code are:
main.c: In function ‘new_task’:
main.c:103:31: error: incompatible types when assigning to type ‘User’ {aka ‘struct user’} from type ‘int’
103 | database[i].username[0] = '\0'; /* username (not attributed) */
| ^~~~
main.c:104:32: error: ‘(Activity *)&(database + (sizetype)((long unsigned int)i * 948))->activity’ is a pointer; did you mean to use ‘->’?
104 | strcpy(database[i].activity.name, "TO DO"); /* activity */
| ^
| ->

The error is on this line:
database[i].username[0] = '\0';
This is because username is declared to be a User array:
typedef struct task {
int id;
char des[LENGTH_TASK_DESCR]; /* description */
User username[LENGTH_USERNAME];
Activity activity[LENGTH_ACTIVITY_NAME];
int etc; /* Estimated Time of Completion */
int start_time;
} Task;
That looks like an error in the field declaration and should instead be:
char username[LENGTH_USERNAME];

The expression user_database[i].username[0] is of type char, so you need to assign a char and not a string to it.
user_database[i].username[0] = '\0';
Note the single quotes not double quotes '\0'.

Related

Read a file during execution of C program and store all the items and their respective prices in an array of structure items

How can I solve this problem given to us in our lab test? I have tried manier times but failed. I have started learning C since 2 months.
Q:
Read a file named food.txt during execution of your program to store all these items and their respective prices in an array of structure item.
Note: 'struct item' contains 'char name' and 'int price'.
Also, first line of food.txt gives number of entries.
(command: ./a.out < food.txt).
Edit: This is my code. I can't find my mistake.
#include<stdio.h>
//Defining the struct
typedef struct {
char name[25];
int price;
}item;
int main(){
int n; //Number of entries
int i,j,k,flag;
int temp[40];
scanf("%d",&n);//first line gives number of entries as input
item items[n]; //creating our items struct
int c = getchar();
for(i=0;i<n;i++){
items[i].price=0;
for(j=0;;j++){
c=getchar();
if(c<'0' || c>'9') items[i].name[j]=c; //If c is character, it store it in name
if(c=='\n')break; //If c is \n, it breaks from the loop and starts again with i++
temp[j]=c;
}
for(j=0;;j++){
if(temp[j]>=0 && temp[j]<=9){
items[i].price = (items[i].price)*10 + temp[j];
}
else if(temp[j]=='\n')break;
}
}
printf("\n.........................................\n");
for(i=0;i<n;i++){
printf("%d. %s %d \n",i+1,items[i].name,items[i].price);
}
}
food.txt
8
hot black tea 5
hot lemon tea 6
hot masala tea 7
hot milk tea 9
hot black coffee 7
hot milk coffee 10
finger potato 45
potato chips 35
Here is an minimal example for understanding how to approach this problem statement:
#include<stdio.h>
#define MAX 100
struct node
{
char name[MAX];
int price;
};
int main(void)
{
int inp;
int count_char=0; //COUNTS THE NUMBER OF CHARACTERS OF A NAME
int count_arr=0; //COUNTS THE NUMBER OF SEPARATE NAME-PRICE STRUCTURES USED
struct node EMPTY={{'\0'},0}; //EMPTY STRUCTURE FOR DEFAULT INITIALIZATION
struct node arr[]={[0 ... 99]=EMPTY}; //ARRAY OF STRUCTURES CONTANING 100 ELEMENTS
int temp_count=0;
int count_space=0; //COUNT NUMBER OF SPACES WITHIN THE STRING
while((inp=getchar())!=EOF)
{
if(inp=='\n')
{
count_space=0;
count_arr++;
count_char=0;
continue;
}
if((((inp>='A')&&(inp<='Z'))||((inp>='a')&&(inp<='z')))||(inp==' '))
{
if((count_char==0)&&(inp==' ')) //LEADING SPACE HANDLING
{
continue;
}
if(inp==' ') //SPACE WITHIN STRINGS HANDLING
{
++count_space;
}
else
count_space=0;
if(count_space>1)
continue;
arr[count_arr].name[count_char++]=inp;
}
if((inp>='0')&&(inp<='9'))
{
arr[count_arr].price = (arr[count_arr].price)*10 + inp - '0';
}
}
while(temp_count<count_arr)
{
printf("%s",arr[temp_count].name);
printf("%d\n",arr[temp_count++].price);
}
return 0;
}
If the file contains:
INPUT:
3
xyz 123
abc 89
lmn tub 956
OUTPUT:
xyz 123
abc 89
lmn tub 956
NOTE: There can be tons of things done to streamline this example but this is only a minimal demo.
You can take advantage of the fgets() and sscanf() functions found in stdio.h. This gives the ability to scan the same line of input repeatedly when unexpected input arises, and is generally a better option than using scanf() alone.
In the code below, the line[] array is used to hold the contents of each line of input. This has been made large enough to hold any reasonably sized line, but fgets() ensures that unexpected input will not cause a buffer overflow. More robust code would check for such large inputs anyway, which would cause problems with the remaining input. Note also that the name[] field of the item structure has been enlarged from 25 to 256; there is no reason to be stingy here.
The fgets() function is used to get the first line of input, and if no line is retrieved, or if the first line is non-numeric, an error message is printed to stderr and the program exits with a value of -1.
Then the fgets() function is used again in a loop to read lines of input which are parsed by sscanf(). Here a scanset is used to scan the input line[] and assign to the .name field; it is assumed that the food name contains no numbers. Also note that the .name field will contain any non-numeric characters found before the first digit, so any spaces found before the price will be included in the .name string. These spaces could be trimmed, if desired. Before parsing with sscanf(), the code checks to see if the input line[] is blank, i.e., if the first character is a newline character; if so, the item counter i is decremented, and the loop is continued, skipping any blank lines in the input.
Finally, the contents of the items[] array are displayed for verification.
#include <stdio.h>
struct item {
char name[256];
int price;
};
int main(void)
{
int num_entries; // number of entries, not number of lines
char line[512]; // storage for input lines
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "Empty input file\n");
return -1;
}
if (sscanf(line, "%d", &num_entries) != 1) {
fprintf(stderr, "Formatting error in first line\n");
return -1;
}
struct item items[num_entries];
for (int i = 0; i < num_entries; i++) {
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "Inconsistent file length\n");
return -1;
}
// Do not count blank lines
if (line[0] == '\n') {
--i;
continue;
}
// Assign to struct
if (sscanf(line,
"%255[^0123456789]%d",
items[i].name, &items[i].price) != 2) {
fprintf(stderr, "Formatting error in entry %d\n", i + 1);
return -1;
}
}
// Display contents of array
for (int i = 0; i < num_entries; i++) {
printf("Item %d: %s, $%d\n", i + 1, items[i].name, items[i].price);
}
return 0;
}
Sample interaction:
>$ ./a.out < food.txt
Item 1: hot black tea , $5
Item 2: hot lemon tea , $6
Item 3: hot masala tea , $7
Item 4: hot milk tea , $9
Item 5: hot black coffee , $7
Item 6: hot milk coffee , $10
Item 7: finger potato , $45
Item 8: potato chips , $35
*scnr*:
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define STRING(x) #x
#define STRINGIFY(x) STRING(x)
#define MAX_ITEM_NAME_LENGTH 100
typedef struct item_tag {
char *name;
int price;
} item_t;
item_t item_create()
{
item_t new_item = { NULL, 0 };
return new_item;
}
bool item_read(item_t *item)
{
char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
if (scanf(" %" STRINGIFY(MAX_ITEM_NAME_LENGTH) "[^0-9]%d%*[\n]", name, &price) != 2)
return false;
size_t name_length = strlen(name);
if (name_length && isspace((int)name[name_length - 1]))
name[--name_length] = '\0';
item->name = malloc(strlen(name) + 1);
strcpy(item->name, name);
item->price = price;
return true;
}
void item_print(item_t *item, size_t longest_name_length)
{
printf("%-*s %4d\n", (int)longest_name_length, item->name, item->price);
}
void item_destroy(item_t *item)
{
free(item->name);
}
typedef struct products_list_tag {
size_t size;
item_t *items;
size_t longest_name_length;
} products_list_t;
products_list_t products_list_create(void)
{
products_list_t new_products_list = { 0, NULL, 0 };
return new_products_list;
}
bool products_list_read(products_list_t *products_list)
{
size_t num_items;
if (scanf(" %zu%*[\n]", &num_items) != 1)
return false;
else if (!num_items)
return true;
item_t *new_items = calloc(num_items, sizeof *new_items);
size_t num_valid_items = 0;
size_t longest_name_length = 0;
for (size_t i = 0; i < num_items && !feof(stdin); ++i) {
new_items[i] = item_create();
if (!item_read(&new_items[i]))
--i;
else {
++num_valid_items;
size_t name_length = strlen(new_items[i].name);
if (longest_name_length < name_length)
longest_name_length = name_length;
}
}
if (num_valid_items != num_items) {
free(new_items);
return false;
}
new_items = realloc(new_items, num_valid_items * sizeof *new_items);
products_list->items = new_items;
products_list->size = num_valid_items;
products_list->longest_name_length = longest_name_length;
return true;
}
void products_list_print(products_list_t *products_list)
{
for (size_t i = 0; i < products_list->size; ++i)
item_print(&products_list->items[i], products_list->longest_name_length);
}
void products_list_destroy(products_list_t *products_list)
{
for (size_t i = 0; i < products_list->size; ++i)
item_destroy(&products_list->items[i]);
free(products_list->items);
products_list->size = 0;
}
int main(void)
{
products_list_t products = products_list_create();
if (!products_list_read(&products)) {
perror("Failed to read products list!\n\n");
products_list_destroy(&products);
return EXIT_FAILURE;
}
products_list_print(&products);
products_list_destroy(&products);
}
Update:
Just read about a stupid no-other-headers-than-<stdio.h> restriction in a comment on a temporarily deleted, now resored answer.
#include <stdio.h>
#define STRING(x) #x
#define STRINGIFY(x) STRING(x)
#define MAX_ITEM_NAME_LENGTH 100
#define MAX_PRODUCTS_LIST_ITEMS_COUNT 100
/* BEGIN stupid no-other-headers-than-<stdio.h> workaround */
#define MY_EXIT_FAILURE -1
#define true 1
#define false 0
typedef int my_bool;
size_t my_strlen(char const *str)
{
char const *p = str;
while (*p) ++p;
return p - str;
}
char* my_strcpy(char *dst, char *src)
{
char *p = dst;
while (*dst++ = *src++);
return p;
}
/* END stupid no-other-headers-than-<stdio.h> workaround */
typedef struct item_tag {
char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
} item_t;
my_bool item_read(item_t *item)
{
char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
if (scanf(" %" STRINGIFY(MAX_ITEM_NAME_LENGTH) "[^0-9]%d%*[\n]", name, &price) != 2)
return false;
size_t name_length = my_strlen(name);
if (name_length && name[name_length - 1] == ' ')
name[--name_length] = '\0';
my_strcpy(item->name, name);
item->price = price;
return true;
}
void item_print(item_t *item, size_t longest_name_length)
{
printf("%-*s %4d\n", (int)longest_name_length, item->name, item->price);
}
typedef struct products_list_tag {
size_t size;
item_t items[MAX_PRODUCTS_LIST_ITEMS_COUNT];
size_t longest_name_length;
} products_list_t;
products_list_t products_list_init(void)
{
products_list_t new_products_list = { 0 };
return new_products_list;
}
my_bool products_list_read(products_list_t *products_list)
{
size_t num_items;
if (scanf(" %zu%*[\n]", &num_items) != 1)
return false;
else if (!num_items)
return true;
size_t num_valid_items = 0;
size_t longest_name_length = 0;
for (size_t i = 0; i < num_items && !feof(stdin); ++i) {
if (!item_read(&products_list->items[i]))
--i;
else {
++num_valid_items;
size_t name_length = my_strlen(products_list->items[i].name);
if (longest_name_length < name_length)
longest_name_length = name_length;
}
}
if (num_valid_items != num_items)
return false;
products_list->size = num_valid_items;
products_list->longest_name_length = longest_name_length;
return true;
}
void products_list_print(products_list_t *products_list)
{
for (size_t i = 0; i < products_list->size; ++i)
item_print(&products_list->items[i], products_list->longest_name_length);
}
int main(void)
{
products_list_t products = products_list_init();
if (!products_list_read(&products)) {
perror("Failed to read products list!\n\n");
return MY_EXIT_FAILURE;
}
products_list_print(&products, stdout);
}
Output:
hot black tea 5
hot lemon tea 6
hot masala tea 7
hot milk tea 9
hot black coffee 7
hot milk coffee 10
finger potato 45
potato chips 35

Arm-Linux LCD_show_jpg picture ," Segmentation fault " problem?

I wanna show 3 .jpg pictures on LCD ,but the program crashed, it seems that the pointer did not init,here is the main() function:
#include <stdio.h>
#include <pthread.h>
int main(int argc,char **argv)
{
lcd_open("/dev/fb0");
int i = 0;
char* pic_path[3] = {"./jpeg/1.jpg","./jpeg/2.jpg","./jpeg/3.jpg"};
while(1)
{
if(i == 3)
{
i = 0;
}
lcd_draw_jpg(0, 0, pic_path[i], NULL, 0, 0);
pthread_testcancel();
sleep(1);
i++;
}
return 0;
}
It just show the 1st picture.
here is the display function Lcd.c
int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half)
{
/*定义解码对象,错误处理对象*/
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
char *pcolor_buf = g_color_buf
char *pjpg
unsigned int i=0;
unsigned int color =0;
unsigned int count =0;
unsigned int x_s = x;
unsigned int x_e ;
unsigned int y_e ;
int jpg_fd;
unsigned int jpg_size;
unsigned int jpg_width;
unsigned int jpg_height;
//lcd_open("/dev/fb0");
if(pjpg_path!=NULL)
{
/* 申请jpg资源,权限可读可写 */
jpg_fd=open(pjpg_path,O_RDWR);
if(jpg_fd == -1)
{
printf("open %s error\n",pjpg_path);
return -1;
}
/* 获取jpg文件的大小 */
jpg_size=file_size_get(pjpg_path);
/* 为jpg文件申请内存空间 */
pjpg = malloc(jpg_size);
/* 读取jpg文件所有内容到内存 */
read(jpg_fd,pjpg,jpg_size);
}
else
{
jpg_size = jpg_buf_size;
pjpg = pjpg_buf;
}
/*注册出错处理*/
cinfo.err = jpeg_std_error(&jerr);
/*创建解码*/
jpeg_create_decompress(&cinfo);
/*直接解码内存数据*/
jpeg_mem_src(&cinfo,pjpg,jpg_size);
/*读文件头*/
jpeg_read_header(&cinfo, TRUE);
/*开始解码*/
jpeg_start_decompress(&cinfo);
if(jpg_half)
{
x_e = x_s+(cinfo.output_width/2);
y_e = y +(cinfo.output_height/2);
/*读解码数据*/
while(cinfo.output_scanline < cinfo.output_height)
{
pcolor_buf = g_color_buf;
/* 读取jpg一行的rgb值 */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
/* 再读取jpg一行的rgb值 */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
for(i=0; i<(cinfo.output_width/2); i++)
{
/* 获取rgb值 */
color = *(pcolor_buf+2);
color = color | *(pcolor_buf+1)<<8;
color = color | *(pcolor_buf)<<16;
/* 显示像素点 */
lcd_draw_point(x,y,color);
pcolor_buf +=6;
x++;
}
/* 换行 */
y++;
x = x_s;
}
}
else
{
x_e = x_s+cinfo.output_width;
y_e = y +cinfo.output_height;
/*读解码数据*/
while(cinfo.output_scanline < cinfo.output_height )
{
pcolor_buf = g_color_buf;
/* read one line's of jpg */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
for(i=0; i<cinfo.output_width; i++)
{
/* get rgb value */
color = *(pcolor_buf+2);
color = color | *(pcolor_buf+1)<<8;
color = color | *(pcolor_buf)<<16;
/* display pixel point */
lcd_draw_point(x,y,color);
pcolor_buf +=3;
x++;
}
/* 换行 */
y++;
x = x_s;
}
}
/*解码完成*/
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
if(pjpg_path!=NULL)
{
/* 关闭jpg文件 */
close(jpg_fd);
/* 释放jpg文件内存空间 */
free(pjpg);
}
close_lcd();
return 0;
}
this looks like Memory Leak or something else......
these seems a little weird,and

Whats wrong when copying my nested struct?

I code C to get better in programming and study... and have program that should generate a static web-page. It also saves the project as a text-file. I have separate functions to make object (realloc and put a new struct...), and have extracted the problem-code to a short program for this occasion... It's just for reading the 'project'. When I run it says:
Segmentation fault (core dumped)
in the middle of the print_1_content
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SELL_ITEM 1
#define PARAGRAPH_ITEM 2
struct SellItem {
char title[50];
int nr_of_img;
char ** image_files;//array of strings
};
struct ParagraphItem{
char * text;
};
union ContentItem{//one of the following only
struct SellItem s_item;
struct ParagraphItem p_item;
};
struct Content{
int type;//1=sellitem 2=paragraph
union ContentItem c_item;
};
int open_items_file(struct Content **, int *, char *);
int free_1_item(struct Content *);
struct Content import_1_content(char *);
void increase(struct Content**, int *);
void print_1_content(struct Content *);
struct Content import_1_content(char *);
int free_1_item(struct Content *);
int main (void)
{
struct Content * content;
int content_count=0;
open_items_file(&content, &content_count, "all_items.txt");
return 0;
}
int open_items_file(struct Content ** content, int * number_of_content, char * filename){
printf("open_items_file %s\n", filename);
FILE *fp = fopen(filename, "r");
char * line = NULL;
size_t len = 0;
ssize_t read;
int counter=0;
if(fp==NULL){
return 0;
}
//for each row
while ((read = getline(&line, &len, fp)) != -1) {
if((line[0]=='S' || line[0]=='P') && line[1]=='-'){
if(line[3]==':'){
if(line[2]=='I'){
increase(content, number_of_content);
*content[(*number_of_content)-1] = import_1_content(line);
}
else{
//not sell/paragraph item
}
}//end if line[3]==':'
}//end if line[0] =='S' eller 'P'
counter++;
}
free(line);
fclose(fp);
return counter;
}
void increase(struct Content** content, int *nr_of_content){
if((*nr_of_content)==0){
*content = malloc(sizeof(struct Content));
}
else{
*content = realloc(*content, (*nr_of_content+1) * sizeof(struct Content));
}
(*nr_of_content)++;
}
void print_1_content(struct Content * content){
//Print info
}
struct Content import_1_content(char * text_line){
struct Content temp_content_item;
char * line_pointer = text_line;
char c;
line_pointer += 4;
if(text_line[0]=='S'){
temp_content_item.type = SELL_ITEM;
temp_content_item.c_item.s_item.nr_of_img=0;
int i=0;
char * temp_text;
while(*line_pointer != '|' && *line_pointer != '\n' && i < sizeof(temp_content_item.c_item.s_item.title)-1){
temp_content_item.c_item.s_item.title[i] = *line_pointer;
i++;//target index
line_pointer++;
}
temp_content_item.c_item.s_item.title[i]='\0';
i=0;
//maybe images?
short read_img_counter=0;
if(*line_pointer == '|'){
line_pointer++; //jump over '|'
//img-file-name separ. by ';', row ends by '\n'
while(*line_pointer != '\n'){//outer image filename -loop
i=0;
while(*line_pointer != ';' && *line_pointer != '\n'){//steps thr lett
c = *line_pointer;
if(i==0){//first letter
temp_text = malloc(2);
}
else if(i>0){
temp_text = realloc(temp_text, i+2);//extra for '\0'
}
temp_text[i] = c;
line_pointer++;
i++;
}
if(*line_pointer==';'){//another image
line_pointer++;//jump over ';'
}
else{
}
temp_text[i]='\0';
//allocate
if(read_img_counter==0){//create array
temp_content_item.c_item.s_item.image_files = malloc(sizeof(char*));
}
else{//extend array
temp_content_item.c_item.s_item.image_files = realloc(temp_content_item.c_item.s_item.image_files, sizeof(char*) * (read_img_counter+1));
}
//allocate
temp_content_item.c_item.s_item.image_files[read_img_counter] = calloc(i+1, 1);
//copy
strncpy(temp_content_item.c_item.s_item.image_files[read_img_counter], temp_text, strlen(temp_text));
read_img_counter++;
temp_content_item.c_item.s_item.nr_of_img = read_img_counter;
}
}
else{
printf("Item had no img-files\n");
}
}
else{ // text_line[0]=='P'
temp_content_item.type = PARAGRAPH_ITEM;
temp_content_item.c_item.p_item.text = calloc(strlen(text_line)-4,1);
int i=0;
while(*line_pointer != '\0' && *line_pointer != '\n'){
temp_content_item.c_item.p_item.text[i] = *line_pointer;
i++;
line_pointer++;
}
}
print_1_content(&temp_content_item);
return temp_content_item;
}
int free_1_item(struct Content * item){
if(item->type==SELL_ITEM){
if(item->c_item.s_item.nr_of_img > 0){
//Freeing img-names
for(int i=0; i<item->c_item.s_item.nr_of_img; i++){
free(item->c_item.s_item.image_files[i]);
}
}
return 1;
}
else if(item->type==PARAGRAPH_ITEM){
//freeing p_item
free(item->c_item.p_item.text);
return 1;
}
else{
printf("error: unknown item\n");
}
return 0;
}
The text file to read (all_items.txt) is like this, ends with a new-line, for the two content types of "sell-item" and "paragraph-item":
S-I:Shirt of cotton|image1.jpg;image2.jpg;image3.jpg
P-I:A paragraph, as they are called.
S-I:Trousers, loose style|image4.jpg
So the problem as you've discovered is on this line:
*content[(*number_of_content)-1] = temp_content_item2;
It's because of operate precedence because *content[(*number_of_content)-1] is not the same as (*content)[(*number_of_content)-1], it's actually doing *(content[(*number_of_content)-1]). So your code is doing the array indexing and then de-referencing which is pointing at some random place in memory. Replace that line with this and that will fix the current problem.
(*content)[(*number_of_content)-1] = temp_content_item2;

Comparing contents of files for groupings of words

Background:
I am currently working on a project. The main objective is to read files and compare groupings of words. Only user interaction will be to specify group length. My programs are placed into a directory. Inside that directory, there will be multiple textfiles(Up to 30). I use
system("ls /home/..... > inputfile.txt");
system("ls /home/..... > inputfile.txt");
From there, I open the files from inputfile.txt to read for their contents.
Now to the actual question/problem part.
The method I am using for this is a queue because FIFO. (Code "link.c":http://pastebin.com/rLpVGC00
link.c
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "linkedlist.h"
struct linkedList
{
char *data;
int key;
int left;
int right;
int size;
};
LinkedList createLinkedList(int size)
{
LinkedList newLL = malloc(sizeof *newLL);
newLL->data = malloc(sizeof(int) * (size+1));
newLL->size = size;
newLL->left = 0;
newLL->right = 0;
return newLL;
}
bool isFull(LinkedList LL)
{
return abs(abs(LL->left)- abs(LL->right)) == LL->size;
}
void insertFront(LinkedList LL, char *newInfo)
{
if(isFull(LL))
{
printf("FULL");
exit(1);
}
LL->data[((--(LL->left) % LL->size) + LL->size) % LL->size] = newInfo;
}
bool isEmpty(LinkedList LL)
{
return LL->left == LL->right;
}
const char * removeEnd(LinkedList LL)
{
if(isEmpty(LL))
{
return "EMPTY";
//exit(1);
}
return LL->data[((--(LL->right) % LL->size) + LL->size) % LL->size];
}
I get two warnings when I compile with link.c and my main (Start11.c)
link.c: In function ‘insertFront’:
link.c:39:64: warning: assignment makes integer from pointer without a cast [enabled by default]
LL->data[((--(LL->left) % LL->size) + LL->size) % LL->size] = newInfo;
^
link.c: In function ‘removeEnd’:
link.c:54:5: warning: return makes pointer from integer without a cast [enabled by default]
return LL->data[((--(LL->right) % LL->size) + LL->size) % LL->size];
^
FULL start11.c code: http://pastebin.com/eskn5yxm .
From bulk of read() function that I have questions about:
fp = fopen(filename, "r");
//We want two word or three word or four word PHRASES
for (i = 0; fgets(name, 100, fp) != NULL && i < 31; i++)
{
char *token = NULL; //setting to null before using it to strtok
token = strtok(name, ":");
strtok(token, "\n");//Getting rid of that dirty \n that I hate
strcat(fnames[i], token);
char location[350];
//Copying it back to a static array to avoid erros with fopen()
strcpy(location, fnames[i]);
//Opening the files for their contents
fpp = fopen(location, "r");
printf("\nFile %d:[%s] \n", i+1, fnames[i]);
char* stringArray[400];
//Reading the actual contents
int y;
for(j = 0; fgets(info,1600,fpp) != NULL && j < 1600; j++)
{
for( char *token2 = strtok(info," "); token2 != NULL; token2 = strtok(NULL, " ") )
{
puts(token2);
++y;
stringArray[y] = strdup(token2);
insertFront(index[i],stringArray[y]);
}
}
}
//Comparisons
char take[20010],take2[200100], take3[200100],take4[200100];
int x,z;
int count, count2;
int groupV,groupV2;
for(x = 0; x < 10000; ++x)
{
if(removeEnd(index[0])!= "EMPTY")
{
take[x] = removeEnd(index[0]);
}
if(removeEnd(index[1])!= "EMPTY")
{
take2[x] = removeEnd(index[1]);
}
if(removeEnd(index[2])!= "EMPTY")
{
take3[x] = removeEnd(index[2]);
}
}
for(z = 0; z < 10; z++)
{
if(take[z] == take2[z])
{
printf("File 1 and File 2 are similar\n");
++count;
if(count == groupL)
{
++groupV;
}
}
if(take[z] == take3[z])
{
printf("File 1 and File 3 are similar\n");
++count2;
if(count == groupL)
{
++groupV2;
}
}
}
Are those two warnings before the reason why when I try to compare the files it'll not be correct? (Yes I realize I "hardcoded" the comparisons. That is just temporary till I get some of this down...)
I'll post header files as a comment. Won't let me post more than two links.
Additional notes:
removeEnd() returns "EMPTY" if there is if there is nothing left to remove.
insertFront() is a void function.
Before I created this account so I can post, I read a previous question regarding strttok and how if I want to insert something I have to strdup() it.
I have not added my free functions to my read() function. I will do that last too.
start.h (pastebin.com/NTnEAPYE)
#ifndef START_H
#define START_H
#include "linkedlist.h"
void read(LinkedList LL,char* filename, int lineL);
#endif
linkedlist.h (pastebin.com/ykzbnCTV)
#include <stdlib.h>
#include <stdio.h>
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
typedef int bool;
typedef struct linkedList *LinkedList;
LinkedList createLinkedList(int size);
bool isFull(LinkedList LL);
void insertFront(LinkedList LL, char *newInfo);
const char * removeEnd(LinkedList LL);
bool isEmpty(LinkedList LL);
#endif
The main problem is around the removeEnd (resp. insertFrom) function:
const char * removeEnd(LinkedList LL)
{
if (...)
return "EMPTY";
else
return LL->data[xxx];
you return a const char * in the first return but a char in the second return, hence the warning, which is a serious one.
And when you compare return value to "EMPTY" in the caller, it's just wrong: you should use strcmp instead of comparing arrays which may be the same depending on compilers which group same strings in the same location, but only by chance (and not portable!)

Overlapping and too long integer values in dynamic c structs

I have the following problem.
I need to create a list of savestates with dynamical length. That's why I decided to create a list by defining some structs and connecting dynamically created structs together to build a list of structs which can dynamically be extended and so on.
However, some things seem to not work at all. Here's the relevant code first:
saves.h:
#ifndef SAVES_H
#include<time.h>
#define SAVES_H
#define SVS_STRLEN 500
#define SVS_FILE "savefile.dat"
#define True 1
#define False 0
typedef struct SVS_STATE SVS_STATE;
typedef struct SVS_STATES SVS_STATES;
struct SVS_STATE {
int i_playfield[6][7];
int i_turn;
time_t i_time;
void *next;
};
struct SVS_STATES {
SVS_STATE *states;
int count;
int loaded;
};
void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time);
void SVS_Debug_State(SVS_STATE *state);
void SVS_Format_State(SVS_STATE *state, char text[]);
SVS_STATE *SVS_Get_State(int number);
#endif
saves.c:
#include "saves.h"
#include<string.h>
#include<time.h>
SVS_STATE *SVS_Get_State(int number)
{
int i = 1;
SVS_STATE *state;
if (svs_current_state.loaded == False) return NULL;
if (number > svs_current_state.count) return NULL;
state = svs_current_state.states;
printf("printing state 1:");
SVS_Debug_State(state);
while( i < number)
{
i++;
state = (SVS_STATE*)(state->next);
printf("printing state %i:", i);
SVS_Debug_State(state);
}
return state;
}
void SVS_Format_State(SVS_STATE *state, char text[])
{
int i, j;
if (svs_current_state.loaded == False) return;
text[0] = '\0';
strcat(text, "{\0");
for (i = 0; i < X_SIZE; i++)
{
strcat(text, "{\0");
for(j = 0; j < Y_SIZE; j++)
{
strcat(text, "%i,\0");
sprintf(text, text, state->i_playfield[i][j]);
}
strcat(text, "}\0");
}
strcat(text, "};%i;%i\n\0");
sprintf(text, text, state->i_turn, state->i_time);
printf("\nFormatted state:%s\n", text);
}
void SVS_Debug_State(SVS_STATE *state)
{
char text[SVS_STRLEN];
SVS_Format_State(state, text);
printf("%s\n", text);
}
void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time)
{
int i, j;
SVS_STATE *laststate, *newstate;
newstate = (SVS_STATE*)malloc(sizeof(SVS_STATE));
printf("adding state with time:%i\n", i_time);
if (svs_current_state.loaded == False) return;
for (i = 0; i < 6; i++)
for (j = 0; j < 7; j++)
newstate->i_playfield[i][j] = i_playfield[i][j];
newstate->i_turn = i_turn;
newstate->i_time = i_time;
newstate->next = NULL;
printf("initialized state:");
SVS_Debug_State(newstate);
if (svs_current_state.coun > 0)
{
laststate = SVS_Get_State(svs_current_state.count);
laststate->next = (void*)newstate;
} else
svs_current_state.states=newstate;
svs_current_state.count++;
}
int main()
{
int i_playfield[6][7] = {0};
// mark saves library as loaded here, but removed function, since it
// just sets svs_current_state.loaded (which is the global struct of
// type SVS_STATES) to 1
SVS_Add_State(i_playfield, 1, time(NULL));
i_playfield[0][0] = 2;
SVS_Add_State(i_playfield, 2, time(NULL));
return 0;
}
The actual problems I encountered while using the printf's and Debug_State calls in these functions:
- the i_time I give is printed out once in Add_State(), correctly. Means it is a legal time and stuff, but when printed out after creating the full state by using Format_State() the string is 50 percent to long and the last part is displayed twice, for example:
if the time is 12345678, it is displayed correctly while debugging in Add_State, but Format_State() displays 123456785678.
- second problem: the first state added works, more or less, fine. But after adding a second one, printing the first state (retrieved by using Get_State and formatted with Format_State) prints a mixture of two states, for example something like this:
state 1: {{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}...
{0,0,0,0,0,0}};1;123456785678
state 2: {{0,0,0,0,0,0}{0,0,0,0,0,0}...
{0,0,0,0,0,0}};2;1234567856785678,0}{0,0,0,0,0,0}...
Thanks for reading.
These calls
sprintf(text, text, ...
invoke undefined behaviour, as the target buffer and one of the other arguments overlap.
From the POSIX specs to sprintf():
If copying takes place between objects that overlap as a result of a call to sprintf() [...], the results are undefined.

Resources