Cannot retrieve all the data from Hashtable - c

I am trying to code an algorithm in C that reads a huge file ( more than 750.000 lines) , separates each line by some specified delimiters , and saves the data into a structure , which is then saved into a Hashtable. Everything goes fine until I want to print one specific data for each row of the Hashtable: the output is good for some rows , but the console is just printing some random symbols for others (which means memory leaks maybe? ).
I am trying to figure what can cause this problem. If I isolate the code that separate the line and saves it into the structure, and execute it for each line separately, it works fine, everything is printed as expected.
I have also tried to do it without dynamic allocation but it works a bit better with it as I was getting the infamous "Segmentation fault"
Here is the code that splits the line and saves it:
unsigned int hash(unsigned int id) {
unsigned int hashage = 5381; //Valeur arbitraire
unsigned int mdop = 10; //faire un modulo obtenir l'unite
int idtmp = id;
while (mdop < id) {
idtmp = id%mdop;
hashage = ((hashage << 6) + hashage) + idtmp;
mdop *= 10;
}
return hashage % NB_CASES_HASH;
}
void initiate_hashtable(Hashtable hashtable) {
int i = 0;
for (; i < NB_CASES_HASH; i++) {
hashtable[i] = NULL;
}
}
void ajout_entete(Liste *liste, Oeuvre *oeuvre) {
Liste p = malloc(sizeof(Cellule));
if (!p) exit(EXIT_FAILURE);
p->oeuvre = *oeuvre;
p->suiv = *liste;
//Si on imprime ici , tout va bien , les données sont correctes
*liste = p;
}
void ajout_annee(Liste *liste, Oeuvre *oeuvre) { //ajout trié par année pour recherche plus rapide
if (!(*liste) || oeuvre->year <= (*liste)->oeuvre.year)
ajout_entete(liste,oeuvre);
else {
if (oeuvre->year >= (*liste)->oeuvre.year)
ajout_annee(&(*liste)->suiv, &oeuvre);
}
}
Oeuvre peuple_oeuvre(char line[MAX_CHARS_LINE]) {
int i = 0, j = 1, cmpt = 0;
char strings[CHAMPS_OEUVRE][MAX_SIZE];
char carac = *(line);
char mot[MAX_SIZE];
mot[0] = carac;
bool isSuivi = false;
Oeuvre oeuvre;
while (carac != '\n') {
if (carac == ',') {
if(isSuivi) {
mot[j - 1] = '\"';
mot[j] = '\0';
isSuivi = false;
} else
mot[j - 1] = '\0';
strcpy(strings[i], mot);
j = 0;
i++;
} else
if (carac == '\"') {
cmpt++;
carac = *(line + cmpt);
while (carac != '\"') {
mot[j] = carac;
j++;
cmpt++;
carac = *(line + cmpt);
}
isSuivi = true;
}
cmpt++;
carac = *(line + cmpt);
mot[j] = carac;
j++;
}
mot[j] = '\0';
strcpy(strings[i], mot);
//Assignation des valeurs :
oeuvre.id = atoi(strings[0]);
oeuvre.accession_number = strdup(strings[1]);
oeuvre.artiste.nomArtiste = strdup(strings[2]);
oeuvre.artiste.artistRole = strdup(strings[3]);
oeuvre.artiste.artistId = atoi(strings[4]);
oeuvre.titre = strdup(strings[5]);
oeuvre.url = strdup(strings[CHAMPS_OEUVRE]);
oeuvre.year = atoi(strings[9]);
return oeuvre;
}
void peuple_hashtable(Hashtable hashtable) { // Peuplement par redirection
char ligne[MAX_CHARS_LINE];
fgets(ligne, MAX_CHARS_LINE, stdin);
Oeuvre *oeuvre = malloc(sizeof(Oeuvre));
int hashNum;
while (fgets(ligne, MAX_CHARS_LINE, stdin)) {
*oeuvre = peuple_oeuvre(ligne);
hashNum = hash(oeuvre->artiste.artistId);
ajout_annee(&hashtable[hashNum], oeuvre);
}
}
int main() {
Hashtable hashtable;
initiate_hashtable(hashtable);
peuple_hashtable(hashtable);
return 0;
}
And the Oeuvre structure looks like this :
typedef struct oeuvre {
unsigned int id;
char *accession_number;
Artiste artiste;
char *titre;
int year;
char *url;
} Oeuvre;
typedef Liste Hashtable[NB_CASES_HASH];
Thanks in advance.

There are many problems in your code.
If line does not contain a newline or if a double quote is missing, the behavior is undefined.
You do not initialize the string array: if the description has missing fields, the behavior is undefined.
In the part where you save the structure fields, your allocation code is incorrect: you must allocate one more character than the length of the string, strlen(string[0]) + 1 instead of strlen(string[0]) * sizeof(char*).
It would be much simpler to use the POSIX function strdup():
// Assigning the values:
oeuvre.id = atoi(strings[0]);
oeuvre.accession_number = strdup(strings[1]);
oeuvre.artiste.nomArtiste = strdup(strings[2]);
oeuvre.artiste.artistRole = strdup(strings[3]);
oeuvre.artiste.artistId = atoi(strings[4]);
oeuvre.titre = strdup(strings[5]);
oeuvre.url = strdup(strings[CHAMPS_OEUVRE]));
oeuvre.year = atoi(strings[9]);

Solved my issue by declaring the Oeuvre structure like this
typedef struct oeuvre {
unsigned int id;
char accession_number[MAX_CHARS];
Artiste artiste;
char titre[MAX_CHARS];
int year;
char url[MAX_CHARS];
} Oeuvre;
with MAX_CHARS referring to a large number.
So I believe I was not properly allocating the strings before using them, which made them to point to random adresses , resulting in those weird outputs but no error. I also believe that another way of solving this would be to dynamically allocate the chars for each Oeuvre in my function.

Related

How can I return list in C?

I am trying to divide the string with *, and return the divided strings, as follows.
abc*d*efg*hijk -> [abc,d,efg,hijk]
This is my code, where *pattern is the given string, and I first count the number of asterisk(cnt), and make a empty list with length cnt. But it keeps getting the error and I don't get it... Can anyone help me?
error message
value computed is not used (*star_cnt++;)
function returns address of local variable(return units;)
Number 2 is my main error. I can't return the list
int Slice(char *pattern) {
int *star_cnt;
int cnt;
*star_cnt = *pattern;
cnt = 0;
while (*star_cnt != '\0') {
if (*star_cnt == '*') {
cnt++;
}
*star_cnt++;
}
int units[cnt];
int *unit;
int unit_cnt;
unit_cnt = 0;
*unit = *pattern;
while (*unit != '\0') {
int *new_unit;
while (*unit != '*'){
*new_unit = *unit;
unit++;
new_unit++;
}
unit++;
units[unit_cnt] = *new_unit;
}
return units;
I felt there were a number of things wrong, and that looking at a working example might actually help a bit more here.
You could try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
/**
* #fn Slice()
* #param [IN] pattern - pointer to string to be analysed
* #param
* #return pointer to array for strings, array is terminated by NULL
* */
char** Slice(char *pattern) {
char *star_cnt;
int cnt;
char** resultlist;
star_cnt = pattern;
cnt = 0;
while (*star_cnt != '\0') {
if (*star_cnt == '*') {
cnt++;
}
star_cnt++;
}
printf("%d items\n",cnt+1);
resultlist = malloc(sizeof(char*) * (cnt+2));
memset(resultlist,0,sizeof(char*) * (cnt+2));
star_cnt = pattern;
cnt = 0;
resultlist[cnt] = star_cnt;
//printf("item %d: %s\n",cnt,resultlist[cnt]);
cnt++;
while (*star_cnt != '\0') {
if (*star_cnt == '*') {
*star_cnt = '\0';
resultlist[cnt] = star_cnt+1;
//printf("item %d: %s\n",cnt,resultlist[cnt]);
cnt++;
}
star_cnt++;
}
return resultlist;
}
int main()
{
char working_string[] = "abc*d*efg*hijk";
char* backup_string = strdup(working_string);
char** list = NULL;
list = Slice(working_string);
int i;
i = 0;
if (list != NULL)
{
while(list[i] != NULL)
{
printf("%d : %s\n",i,list[i]);
i++;
}
free(list);
}
printf("original_string = %s\n",backup_string);
free(backup_string);
}
It produces an output like this:
4 items
0 : abc
1 : d
2 : efg
3 : hijk
original_string = abc*d*efg*hijk
The Slice function basically returns a pointer to char* strings, and the array list is terminated with a NULL in the last element. Keep in mind that in this solution the original string is modified so it cannot be used again.
For storing and returning the result you can also define string container like:
struct c_str_container{
char **arr;
size_t size;
};
And then you can define functions like init_c_str_container, add_element_to_c_str_container and free_c_str_container for dealing with the container.
then you can write the substrings function with using strchr function for finding the delimiters and splitting the string in to sub-strings.
Finally you can use this function to create the container and then after displaying the result from the container (and possibly doing other things with the container) you free the allocated memory by the predefined function free_c_str_container:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct c_str_container{
char **arr;
size_t size;
};
void init_c_str_container(struct c_str_container *container){
container->arr = NULL;
container->size = 0;
}
int add_element_to_c_str_container(struct c_str_container *container, const char *txt, size_t length){
char **newarr = (char **) realloc(container->arr, (container->size + 1) * (sizeof(char *)));
if(!newarr){
newarr = (char **) malloc((container->size + 1) * (sizeof(char *)));
if(!newarr){
return -1;
}else{
for(size_t counter = container->size; counter--;){
newarr[counter] = container->arr[counter];
}
if(container->size){
free(container->arr);
}
}
}
newarr[container->size] = malloc((length + 1) * sizeof(char));
memcpy(newarr[container->size], txt, length);
newarr[container->size][length] = '\0';
container->arr = newarr;
++container->size;
return 0;
}
void free_c_str_container(struct c_str_container *container){
for(size_t counter = container->size; counter--;){
free(container->arr[counter]);
}
free(container->arr);
container->size = 0;
}
struct c_str_container substrings(const char *input, const char delimiter){
const char *input_end = input + strlen(input);
struct c_str_container container;
init_c_str_container(&container);
while(strchr(input, delimiter) == input){
++input;
}
const char *end_point;
while((end_point = strchr(input, delimiter))){
add_element_to_c_str_container(&container, input, (end_point - input));
while(strchr(end_point, delimiter) == end_point){
++end_point;
}
input = end_point;
}
if(input < input_end){
add_element_to_c_str_container(&container, input, (input_end - input));
}
return container;
}
int main(void) {
struct c_str_container container = substrings("***as***we*grow*up", '*');
printf("number of elements is : %zu\n", container.size);
for(size_t counter = 0; counter < container.size; ++counter){
printf("element %zu is : %s\n", counter, container.arr[counter]);
}
free_c_str_container(&container);
printf("now elements are : %zu\n", container.size);
return EXIT_SUCCESS;
}
for the test string ="***as***we*grow*up" delimeter = '*' the result of the program is:
number of elements is : 4
element 0 is : as
element 1 is : we
element 2 is : grow
element 3 is : up
now elements are : 0

Problems on computing statistics and parsing a text file

a must be simple question but I couldn't manage to do it.
I have to scan on a struct a text file with entries in this format:
{"data1","data2",number1,number2}
And compute first populating a struct.
Text of the exercise:
Consider the definition of the following structure
typedef struct {
char teamHome [30];
char teamHost [30];
int goalSquadraHome;
int goalSquadraOspite;
} match;
which is used to represent the result of a football match.
Write a function that takes as parameters an array of games and its size e
returns a result structure containing the following information:
the number of games won by the home team,
the number of games won by the visiting team,
the number of ties,
the name of the team that has scored the most goals in a match.
Then write a program that, given the array containing all 380 Serie A 2019/2020 matches,
print the information contained in the result.
The code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char squadraCasa[30];
char squadraOspite[30];
int golSquadraCasa;
int golSquadraOspite;
} partita;
typedef struct {
int partite_casa;
int partite_ospite;
int pareggi;
char squad_magg_num_goal[30];
} risultato;
int main(){
FILE *fp;
risultato risultati;
int maxgoal = 0;
risultati.partite_casa = 0;
risultati.partite_ospite = 0;
risultati.pareggi = 0;
partita partite[380];
int i=0;
if((fp = fopen("partiteSerieA1920.txt","rt"))==NULL){
printf("Errore nell'apertura del file\n");
exit(1);
}
while(!feof(fp)){
fscanf(fp,"{\"%s\",\"%s\",%d,%d",partite[i].squadraCasa,partite[i].squadraOspite,partite[i].golSquadraCasa,partite[i].golSquadraOspite);
i++;
}
for(i=0;i<380;i++){
if(partite[i].golSquadraCasa>partite[i].golSquadraOspite){
risultati.partite_casa++;
}else if(partite[i].golSquadraCasa<partite[i].golSquadraOspite){
risultati.partite_ospite++;
}else
risultati.pareggi++;
if(partite[i].golSquadraCasa>maxgoal){
strncpy(partite[i].squadraCasa,risultati.squad_magg_num_goal,30);
maxgoal = partite[i].golSquadraCasa;
}
if(partite[i].golSquadraOspite>maxgoal){
strncpy(partite[i].squadraOspite, risultati.squad_magg_num_goal,30);
maxgoal = partite[i].golSquadraOspite;
}
}
fclose(fp);
printf("%d %d %d %s\n",risultati.partite_casa,risultati.partite_ospite,&risultati.pareggi,&risultati.squad_magg_num_goal);
return 0;
}
Please let me know how to arrange it properly.
There may be other issues, but certainly your flow control is wrong. Instead of the incorrect while/feof loop(Why is “while ( !feof (file) )” always wrong?), try something like:
partita *p = partite;
while( 4 == fscanf(fp, "{\"%29s\",\"%29s\",%d,%d",
p->squadraCasa,
p->squadraOspite,
&p->golSquadraCasa,
&p->golSquadraOspite
) ){
p++;
}
Give this a try, its a bit of a different approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char squadraCasa[30];
char squadraOspite[30];
int golSquadraCasa;
int golSquadraOspite;
} partita;
typedef struct
{
int partite_casa;
int partite_ospite;
int pareggi;
char squad_magg_num_goal[30];
} risultato;
// solves given problem and stores results in risultato struct
risultato *getResult(partita **playedGames, int size)
{
risultato *result = malloc(sizeof(risultato));
result->partite_casa = 0;
result->partite_ospite = 0;
result->pareggi = 0;
int currentHighest = 0;
for (int i = 0; i < size; i++)
{
if (playedGames[i]->golSquadraCasa > playedGames[i]->golSquadraOspite){
result->partite_casa++;
if(playedGames[i]->golSquadraCasa > currentHighest ){
currentHighest = playedGames[i]->golSquadraCasa;
strcpy(result->squad_magg_num_goal, playedGames[i]->squadraCasa);
}
}
else if (playedGames[i]->golSquadraCasa < playedGames[i]->golSquadraOspite){
result->partite_ospite++;
if (playedGames[i]->golSquadraOspite > currentHighest){
currentHighest = playedGames[i]->golSquadraOspite;
strcpy(result->squad_magg_num_goal, playedGames[i]->squadraOspite);
}
}
else{
result->pareggi++;
}
}
return result;
}
// This is a custom parser of a line from the file
// data = {"data1","data2",number1,number2}
// return -> partita struct
partita *newGame(char *data){
partita *partite = malloc(sizeof(partita));
char* temp;
// Get Home Team
temp = strchr(data, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraCasa, data + 2);
data = temp+1;
// Get Away Team
temp = strchr(data+1, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraOspite, data + 2);
data = temp + 1;
// Get Home Score
temp = strchr(data + 1, ',');
temp[0] = '\0';
partite->golSquadraCasa = atoi(data + 1);
data = temp + 1;
// Get Away Score
temp = strchr(data, '}');
temp[0] = '\0';
partite->golSquadraOspite = atoi(data);
// Return game
return partite;
}
int main()
{
FILE *fp;
partita **partite = malloc(sizeof(partita *)); // list of size one, currently...
risultato *risultati;
char linea[50];
int indice = 0;
if ((fp = fopen("./partiteSerieA1920.txt", "rt")) == NULL)
{
printf("Errore nell'apertura del file\n");
exit(1);
}
// For each linea in the file, load a game into an array.
while (fgets(linea, 50,fp))
{
//chomp the \n
linea[strlen(linea)-1]='\0';
// increase size of list
partite = realloc(partite, sizeof(partita *) * (indice + 1));
// insert game into array of games
partite[indice] = newGame(linea);
indice++;
}
risultati = getResult(partite, indice);
// Print risultato
printf("\n----RESULT----\nHome Wins: %d\nAway Wins: %d\nTies: %d\nTeam With Most Goals: %s\n\n", risultati->partite_casa, risultati->partite_ospite, risultati->pareggi, risultati->squad_magg_num_goal);
// free all allocated memory then return
for (int i = 0; i < indice;i++){
free(partite[i]);
}
free(partite);
free(risultati);
fclose(fp);
return 0;
}
I was trying to run your code but couldnt get it to parse data from the file properly so i made a quick parser for you (This is in the code above already):
partita *newGame(char *data){
partita *partite = malloc(sizeof(partita));
char* temp;
// Get Home Team
temp = strchr(data, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraCasa, data + 2);
data = temp+1;
// Get Away Team
temp = strchr(data+1, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraOspite, data + 2);
data = temp + 1;
// Get Home Score
temp = strchr(data + 1, ',');
temp[0] = '\0';
partite->golSquadraCasa = atoi(data + 1);
data = temp + 1;
// Get Away Score
temp = strchr(data, '}');
temp[0] = '\0';
partite->golSquadraOspite = atoi(data);
// Return game
return partite;
}
You can always try to use something similar to this to parse strings or lines that you bring in as I find it is more efficient to just code something that you know works to the specification you want.
Let me know if there is some problem with the code or would like to know more about the functionality of this. I tried to keep as much of this in Italian.
Cheers

Problem with assigning string into struct array in c

I am not very skilled at C, especially the dynamic allocation bit of C and I´ve encountered this strange problem. Background is that I have to read input from a user, save it into struct that I defined like this:
typedef struct
{
int camera_ID;
int month;
int day;
int hour;
int min;
char rz[1001];
} cameraEntry;
and then save that struct into an array. Everything works fine, I am able to read the data, create said struct but when it comes to saving it into the array it crashes. I´ve tried assignign the values one by one and found out that the char array causes problems. I´ve tried assigning it char by char but there must be something else I am missing. Here is the code for reading and saving the user input and my main function:
int readEntry(cameraEntry **entries, int *maxN)
{
int n = 0, last = 0;
char brace;
*entries = malloc(*maxN * sizeof(cameraEntry *));
if (scanf("%c", &brace) != 1 || brace != '{')
return -1;
do
{
if (n >= *maxN)
{
*maxN = *maxN * 2;
*entries = realloc(*entries, *maxN * sizeof(cameraEntry *));
}
cameraEntry read = parseInput(&last);
if (read.camera_ID < 0)
return -1;
(*entries)[n].camera_ID = read.camera_ID;
(*entries)[n].month = read.month;
(*entries)[n].day = read.day;
(*entries)[n].hour = read.hour;
(*entries)[n].min = read.min;
//Without this line of code it works like charm
strcpy((*entries)[n].rz, read.rz);
n++;
} while (last == 0);
return n;
}
int main(void)
{
cameraEntry *entries = NULL;
int maxN = 2;
int n = readEntry(&entries, &maxN);
if (n < 0)
{
printf("Wrong input\n");
free(entries);
return 1;
}
printf("Entry count: %d\n", n);
free(entries);
return 0;
}
So please, if you can find the mistake in my code and explain why is it happening I would be very grateful.

How to create a list of word with specific length

Im currently writing a C programming to create a list of word with specific length.
For example, I have a string of ten letter
ABCDEFGHIJ
and wanted to create a list of word where the length is 2 that is
AB,BC,CD,DE,EF,FG,GH,HI,IJ.
For now I can only create
AB,CD,EF,GH,IJ
with my coding
#include<stdio.h>
#include<string.h>
int main()
{
/*q=length of query sequence, W=length of substring, t=(q-w)+1*/
char array[5][3],length[3];
int i=1;
FILE *input;
input=fopen("string.txt", "r");
/*stores and prints the data from the string*/
while(fgets(length,3,input))
{
strcpy(array[i],length);
printf(">%d\n%s\n\n",i,array[i]);
i++;
}
return 0;
}
How can I point the array to starts the next word at position from the second letter not the third letter?
Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char wmers[115];
int i = 1, j = 2;
FILE *input = NULL;
FILE *output;
if (!(input = fopen("exon11.txt", "r"))) {
// Error
return (EXIT_FAILURE);
}
if (!fgets(wmers,115,input)) {
// Error ?
}
printf(">%d\n%s\n\n",i,wmers);
i++;
output=fopen("2.txt", "w");
fputs(wmers,output);
for(int c = fgetc(input); c != EOF; c = fgetc(input))
{
wmers[0] = wmers[1];
wmers[1] = wmers[2];
wmers[2] = wmers[3];
wmers[3] = wmers[4];
wmers[4] = wmers[5];
wmers[5] = wmers[6];
wmers[6] = wmers[7];
wmers[7] = wmers[8];
wmers[8] = wmers[9];
wmers[9] = wmers[10];
wmers[10] = wmers[11];
wmers[11] = wmers[12];
wmers[12] = wmers[13];
wmers[13] = wmers[14];
wmers[14] = wmers[15];
wmers[15] = wmers[16];
wmers[16] = wmers[17];
wmers[17] = wmers[18];
wmers[18] = wmers[19];
wmers[19] = wmers[20];
wmers[20] = wmers[21];
wmers[21] = wmers[22];
wmers[22] = wmers[23];
wmers[23] = wmers[24];
wmers[24] = wmers[25];
wmers[25] = wmers[26];
wmers[26] = wmers[27];
wmers[27] = wmers[28];
wmers[28] = wmers[29];
wmers[29] = wmers[30];
wmers[30] = wmers[31];
wmers[31] = wmers[32];
wmers[32] = wmers[33];
wmers[33] = wmers[34];
wmers[34] = wmers[35];
wmers[35] = wmers[36];
wmers[36] = wmers[37];
wmers[37] = wmers[38];
wmers[38] = wmers[39];
wmers[39] = wmers[40];
wmers[40] = wmers[41];
wmers[41] = wmers[42];
wmers[42] = wmers[43];
wmers[43] = wmers[44];
wmers[44] = wmers[45];
wmers[45] = wmers[46];
wmers[46] = wmers[47];
wmers[47] = wmers[48];
wmers[48] = wmers[49];
wmers[49] = wmers[50];
wmers[50] = wmers[51];
wmers[51] = wmers[52];
wmers[52] = wmers[53];
wmers[53] = wmers[54];
wmers[54] = wmers[55];
wmers[55] = wmers[56];
wmers[56] = wmers[57];
wmers[57] = wmers[58];
wmers[58] = wmers[59];
wmers[59] = wmers[60];
wmers[60] = wmers[61];
wmers[61] = wmers[62];
wmers[62] = wmers[63];
wmers[63] = wmers[64];
wmers[64] = wmers[65];
wmers[65] = wmers[66];
wmers[66] = wmers[67];
wmers[67] = wmers[68];
wmers[68] = wmers[69];
wmers[69] = wmers[70];
wmers[70] = wmers[71];
wmers[71] = wmers[72];
wmers[72] = wmers[73];
wmers[73] = wmers[74];
wmers[74] = wmers[75];
wmers[75] = wmers[76];
wmers[76] = wmers[77];
wmers[77] = wmers[78];
wmers[78] = wmers[79];
wmers[79] = wmers[80];
wmers[80] = wmers[81];
wmers[81] = wmers[82];
wmers[82] = wmers[83];
wmers[83] = wmers[84];
wmers[84] = wmers[84];
wmers[85] = wmers[86];
wmers[86] = wmers[87];
wmers[87] = wmers[88];
wmers[88] = wmers[89];
wmers[89] = wmers[90];
wmers[90] = wmers[91];
wmers[91] = wmers[92];
wmers[92] = wmers[93];
wmers[93] = wmers[94];
wmers[94] = wmers[95];
wmers[95] = wmers[96];
wmers[96] = wmers[97];
wmers[97] = wmers[98];
wmers[98] = wmers[99];
wmers[99] = wmers[100];
wmers[100] = wmers[101];
wmers[101] = wmers[102];
wmers[102] = wmers[103];
wmers[103] = wmers[104];
wmers[104] = wmers[105];
wmers[105] = wmers[106];
wmers[106] = wmers[107];
wmers[107] = wmers[108];
wmers[108] = wmers[109];
wmers[109] = wmers[110];
wmers[110] = wmers[111];
wmers[111] = wmers[112];
wmers[112] = wmers[113];
wmers[113] = wmers[114];
wmers[114] = c;
printf(">%d\n%s\n\n",j,wmers);
j++;
fputs(wmers,output);
}
return (EXIT_SUCCESS);
}
this is the content of exon11.txt.
CTGCTTGTGAATTTTCTGAGACGGATGTAACAAATACTGAACATCATCAACCCAGTAATAATGATTTGAACACCACTGAGAAGCGTGCAGCTGAGAGGCATCCAGAAAAGTATCAGGGTAGTTCTGTTTCAAACTTGCATGTGGAGCCATGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGAAAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGGAAGTAAGGAAACATGTAATGATAGGCGGACTCCCAGCACAGAAAAAAAGGTAGATCTGAATGCTGATCCCCTGTGTGAGAGAAAAGAATGGAATAAGCAGAAACTGCCATGCTCAGAGAATCCTAGAGATACTGAAGATGTTCCTTGGATAACACTAAATAGCAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAGGTTCTGATGACTCACATGATGGGGAGTCTGAATCAAATGCCAAAGTAGCTGATGTATTGGACGTTCTAAATGAGGTAGATGAATATTCTGGTTCTTCAGAGAAAATAGACTTACTGGCCAGTGATCCTCATGAGGCTTTAATATGTAAAAGTGAAAGAGTTCACTCCAAATCAGTAGAGAGTAATATTGAAGACAAAATATTTGGGAAAACCTATCGGAAGAAGGCAAGCCTCCCCAACTTAAGCCATGTAACTGAAAATCTAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAAGAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGACCTACATCAGGCCTTCATCCTGAGGATTTTATCAAGAAAGCAGATTTGGCAGTTCAAAAGACTCCTGAAATGATAAATCAGGGAACTAACCAAACGGAGCAGAATGGTCAAGTGATGAATATTACTAATAGTGGTCATGAGAATAAAACAAAAGGTGATTCTATTCAGAATGAGAAAAATCCTAACCCAATAGAATCACTCGAAAAAGAATCTGCTTTCAAAACGAAAGCTGAACCTATAAGCAGCAGTATAAGCAATATGGAACTCGAATTAAATATCCACAATTCAAAAGCACCTAAAAAGAATAGGCTGAGGAGGAAGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTGTACTGAATTGCAAATTGATAGTTGTTCTAGCAGTGAAGAGATAAAGAAAAAAAAGTACAACCAAATGCCAGTCAGGCACAGCAGAAACCTACAACTCATGGAAGGTAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGACATGACAGCGATACTTTCCCAGAGCTGAAGTTAACAAATGCACCTGGTTCTTTTACTAAGTGTTCAAATACCAGTGAACTTAAAGAATTTGTCAATCCTAGCCTTCCAAGAGAAGAAAAAGAAGAGAAACTAGAAACAGTTAAAGTGTCTAATAATGCTGAAGACCCCAAAGATCTCATGTTAAGTGGAGAAAGGGTTTTGCAAACTGAAAGATCTGTAGAGAGTAGCAGTATTTCATTGGTACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCGTTACTGGAAGTTAGCACTCTAGGGAAGGCAAAAACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGGACTAATTCATGGTTGTTCCAAAGATAATAGAAATGACACAGAAGGCTTTAAGTATCCATTGGGACATGAAGTTAACCACAGTCGGGAAACAAGCATAGAAATGGAAGAAAGTGAACTTGATGCTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCCGTTTTCAAATCCAGGAAATGCAGAAGAGGAATGTGCAACATTCTCTGCCCACTCTGGGTCCTTAAAGAAACAAAGTCCAAAAGTCACTTTTGAATGTGAACAAAAGGAAGAAAATCAAGGAAAGAATGAGTCTAATATCAAGCCTGTACAGACAGTTAATATCACTGCAGGCTTTCCTGTGGTTGGTCAGAAAGATAAGCCAGTTGATAATGCCAAATGTAGTATCAAAGGAGGCTCTAGGTTTTGTCTATCATCTCAGTTCAGAGGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTTTTACAAAACCCATATCGTATACCACCACTTTTTCCCATCAAGTCATTTGTTAAAACTAAATGTAAGAAAAATCTGCTAGAGGAAAACTTTGAGGAACATTCAATGTCACCTGAAAGAGAAATGGGAAATGAGAACATTCCAAGTACAGTGAGCACAATTAGCCGTAATAACATTAGAGAAAATGTTTTTAAAGAAGCCAGCTCAAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGTGGGCTCCAGTATTAATGAAATAGGTTCCAGTGATGAAAACATTCAAGCAGAACTAGGTAGAAACAGAGGGCCAAAATTGAATGCTATGCTTAGATTAGGGGTTTTGCAACCTGAGGTCTATAAACAAAGTCTTCCTGGAAGTAATTGTAAGCATCCTGAAATAAAAAAGCAAGAATATGAAGAAGTAGTTCAGACTGTTAATACAGATTTCTCTCCATATCTGATTTCAGATAACTTAGAACAGCCTATGGGAAGTAGTCATGCATCTCAGGTTTGTTCTGAGACACCTGATGACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAAAATGACATTAAGGAAAGTTCTGCTGTTTTTAGCAAAAGCGTCCAGAAAGGAGAGCTTAGCAGGAGTCCTAGCCCTTTCACCCATACACATTTGGCTCAGGGTTACCGAAGAGGGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAGGATGAAGAGCTTCCCTGCTTCCAACACTTGTTATTTGGTAAAGTAAACAATATACCTTCTCAGTCTACTAGGCATAGCACCGTTGCTACCGAGTGTCTGTCTAAGAACACAGAGGAGAATTTATTATCATTGAAGAATAGCTTAAATGACTGCAGTAACCAGGTAATATTGGCAAAGGCATCTCAGGAACATCACCTTAGTGAGGAAACAAAATGTTCTGCTAGCTTGTTTTCTTCACAGTGCAGTGAATTGGAAGACTTGACTGCAAATACAAACACCCAGGATCCTTTCTTGATTGGTTCTTCCAAACAAATGAGGCATCAGTCTGAAAGCCAGGGAGTTGGTCTGAGTGACAAGGAATTGGTTTCAGATGATGAAGAAAGAGGAACGGGCTTGGAAGAAAATAATCAAGAAGAGCAAAGCATGGATTCAAACTTAG
Given your question, you have tor ead your file char by char, not 2 char by 2 char :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[3] = "";
FILE *input = NULL;
if (!(input = fopen("string.txt", "r"))) {
// Error
return (EXIT_FAILURE);
}
if (!fgets(str,3,input)) {
// Error ?
}
printf("%s\n", str);
for(int c = fgetc(input); c != EOF; c = fgetc(input)) {
str[0] = str[1];
str[1] = c;
printf("%s\n", str);
}
return (EXIT_SUCCESS);
}
But a better way is to read the whole line (like with getline if you are on Linux) and simply display 2 char by 2 char ...
----------
Okay, so this is not really how SO work, but I'm gonna give you a piece of code.
But before that, some general advice :
Begin by testing your code with little data.
I mean, doing a test with an input of 10 char and a len of 2 is good, doing a test with an input of 3K+ char and a len of 100+ is insane. How do you expect to see if your code is good or bad ?
Cut your code in small function.
And do some "unitary" test on these function. That way, if something failed, you will be able to quickly found the bug without a debugger. If the function to retrieve data work but you end up with a wrong result, the maybe the problem lies when you construct your solution. If the result's construction work but you end up with bad value in your file, then maybe it's the writing function that is at fault. etc etc.
Use str* function.
Doing a manually shift to the left with a string of len 2 is ok, but doing it with a string of 115 is insane ! How many time did you spend on that ?
This is the piece of code that will take a string as an input an do what you want.
Since the array can have any length, the last value of the array is NULL.
It's like a string : to know the len, you search for the particuliar value '\0'. Here, it's not '\0' but rather NULL.
The result array and the string's result are good thanks to calloc that implictly set all array pointeur to NULL and all string content to \0.
That's why strncpy doesn't fail.
// TODO Do the description
char** Magic(const char * const input, size_t len)
{
char **array = NULL;
size_t arraySize = 0;
size_t inputLen = strlen(input);
char **returnFunction = NULL;
// Basic check (assert ?)
if (!len) {
// TODO Error message
goto END_FUNCTION;
}
// Calcul of the array length
if (len <= inputLen) {
arraySize = inputLen - len + 1;
}
// Last array value must be NULL in order to know the array length
++arraySize;
if (!(array = calloc(arraySize, sizeof(*array)))) {
// TODO Error message
goto END_FUNCTION;
}
for (size_t i = 0; i < arraySize - 1; ++i) {
if (!(array[i] = calloc(len + 1, sizeof(*array[i])))) {
// TODO Error message
goto END_FUNCTION;
}
strncpy(array[i], input + i, len);
}
returnFunction = array;
array = NULL;
/* GOTO */END_FUNCTION:
if (array) {
for (size_t i = 0; i < arraySize; ++i) {
free(array[i]);
}
free(array);
}
return (returnFunction);
}
int main(void)
{
char *input = "ABCDEFGIHJ";
size_t inputLen = strlen(input);
char **result = NULL;
for (size_t len = 1; len <= inputLen; ++len) {
// Get result
if (!(result = Magic(input, len))) {
// TODO error log ?
continue;
}
// Display result
printf("result for %zu len : ", len);
for (size_t i = 0; result[i]; ++i) {
printf("%s%s", result[i], result[i + 1] ? ", " : "\n");
}
// Free result
for (size_t i = 0; result[i]; ++i) {
free(result[i]);
}
free(result);
result = NULL;
}
return (EXIT_SUCCESS);
}
What's left up to you is : retrieving the data (and then use it in the "input" argument) and display/writing the data.
For both of these, DO A FUNCTION.
And test. lot of test.
Do not forget to check if there is a failure when calling a function.

a global variable cannot be assigned twice

I have faced some problem when doing TDD.
I designed this function:
String *subString;
String *getWordAndUpdate(String *line, char *delimiter) {
String *word = malloc(sizeof(String));
int i;
stringLeftTrim(line);
word->length = 0;
word->startIndex = 0;
for(i = line->startIndex; i < line->length; i++) {
if(line->rawString[i] != ' ') {
word->rawString[i] = line->rawString[i];
line->startIndex++;
word->length++;
} else {
break;
}
}
line->length = line->length - i;
return word;
}
With my String struct:
typedef struct {
char *rawString;
int startIndex;
int length;
} String;
When I call this getWordAndUpdate function the first time it works fine, but when i call second time it says bad memory access.
extern String *subString;
void test_getWordAndUpdate_should_get_the_first_word_from_a_line_of_instruction() {
String oneLineString = {"movwf 0x10", 0, 10};
subString = getWordAndUpdate(&oneLineString, " ,;"); // works fine
TEST_ASSERT_EQUAL('m', subString->rawString[0]);
TEST_ASSERT_EQUAL('o', subString->rawString[1]);
TEST_ASSERT_EQUAL('v', subString->rawString[2]);
TEST_ASSERT_EQUAL('w', subString->rawString[3]);
TEST_ASSERT_EQUAL('f', subString->rawString[4]);
TEST_ASSERT_NOT_EQUAL(' ', subString->rawString[5]);
TEST_ASSERT_NOT_EQUAL('0', subString->rawString[6]);
TEST_ASSERT_NOT_EQUAL('x', subString->rawString[7]);
TEST_ASSERT_NOT_EQUAL('1', subString->rawString[8]);
TEST_ASSERT_NOT_EQUAL('0', subString->rawString[9]);
TEST_ASSERT_EQUAL(5, oneLineString.startIndex);
TEST_ASSERT_EQUAL(5, oneLineString.length);
TEST_ASSERT_EQUAL(0, subString->startIndex);
TEST_ASSERT_EQUAL(5, subString->length);
subString = getWordAndUpdate(&oneLineString, " ,;"); // bad memory access
}
You function getWordAndUpdate modify your object oneLineString in theses lines of code:
line->length--;
line->startIndex++;
So, when you call it a second times, your object in not consistent.
Try to make a copy of oneLineString or find an algo that not modify your parameter.
Maybe, you can use this kind of function:
String *subString;
String *getWordAndUpdate(String *line, char *delimiter) {
String *word = malloc(sizeof(String));
int i;
for (i = 0; line->rawString[i] != ' '; ++i)
word->rawString[i] = line->rawString[i];
word->length = i;
return word;
}
And you don't take care yet of your delimiter parameter.

Resources