How to create a list of word with specific length - c

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.

Related

Segmentation fault after calling, but a very similar function does not get a segmentation fault error

For one of my CS classes we are creating a mini EXT2 file system. In this program I have to make the functions mkdir and creat. In both these functions we call a function called iput which looks like this:
int iput(MINODE *mip)
{
// dispose of minode pointed by mip
// Code in Chapter 11.7.2
INODE *ip;
int i, block, offset;
char buf[BLKSIZE];
if (mip==0)
{
return;
}
mip->refCount--;
printf("mip->refcount = %d\n", mip->refCount);
if (mip->refCount > 0)
{
return 0;
}
if (mip->dirty == 0)
{
return 0;
}
// dec refCount by 1
// still has user
// no need to write back
// write INODE back to disk
block = (mip->ino - 1) / 8 + inode_start;
offset = (mip->ino - 1) % 8;
// get block containing this inode
get_block(mip->dev, block, buf);
printf("get block works in iput\n");
ip = (INODE *)buf + offset; // ip points at INODE
*ip = mip->inode; // copy INODE to inode in block
put_block(mip->dev, block, buf); // write back to disk
printf("put block works in iput\n");
//midalloc(mip); //
mip->refCount = 0;
return 1;
}
Minode is just a struct wrapper that holds an inode inside it, along with other variables. Here is the code for my creat function:
int my_creat(MINODE *pip, char *name)
{
MINODE *mip;
int ino = ialloc(pip->dev);
int bno = balloc(pip->dev);
mip = iget(dev,ino);
INODE *ip = &mip->inode;
ip->i_mode = 0x81A4;
ip->i_uid = running->uid;
ip->i_gid = running->gid;
ip->i_size = 0;
ip->i_links_count = 1;
ip->i_atime = time(0L);
ip->i_ctime = time(0L);
ip->i_mtime = time(0L);
ip->i_blocks = 2;
ip->i_block[0] = bno;
for (int i = 1; i < 15; i++)
{
ip->i_block[i] = 0;
}
mip->dirty = 1;
iput(mip);
char buf[BLKSIZE];
dp = (DIR *)buf;
dp->inode = ino;
strncpy(dp->name, ".", 1);
dp->name_len = 1;
dp->rec_len = 12;
char *cp;
cp = buf + 12;
dp = (DIR*)cp;
dp->inode = pip->ino;
dp->name_len = 2;
strncpy(dp->name, "..", 2);
dp->rec_len = BLKSIZE - 12;
put_block(pip->dev,bno,buf);
enter_name(pip,ino,name);
}
And here is the code for my mkdir function:
int mymkdir(MINODE *pip, char *name)
{
MINODE *mip;
int ino = ialloc(pip->dev);
int bno = balloc(pip->dev);
printf("bno inside mymkdir = %d\n", bno);
printf("ino inside mymkdir = %d\n", ino);
char buf[BLKSIZE];
mip = iget(dev,ino);
printf("goes over iget again\n");
INODE *ip = &mip->inode;
ip->i_mode = 0x41ED;
ip->i_uid = running->uid;
ip->i_gid = running->gid;
ip->i_size = BLKSIZE;
ip->i_links_count = 2;
ip->i_atime = time(0L);
ip->i_ctime = time(0L);
ip->i_mtime = time(0L);
ip->i_blocks = 2;
ip->i_block[0] = bno;
for (int i = 1; i < 15; i++)
{
ip->i_block[i] = 0;
}
mip->dirty = 1;
iput(mip);
printf("goes over iput");
dp = (DIR *)buf;
dp->inode = ino;
strncpy(dp->name, ".", 1);
dp->name_len = 1;
dp->rec_len = 12;
char *cp;
cp += dp->rec_len;
dp = (DIR*)cp;
dp->inode = pip->ino;
dp->name_len = 2;
strncpy(dp->name, "..",2);
dp->rec_len = BLKSIZE - 12;
put_block(pip->dev,bno,buf);
enter_name(pip,ino,name);
}
They are virtually the exact same, but for whatever reason after calling iput in mkdir it crashes and gives me a segmentation fault error, however that does not happen in my creat function. This makes no sense as they are virtually the exact same functions and thus one shouldn't be working if the other isn't working too. Also, they are in the same file, mkdir_creat.c, but the iput function is inside a different C file, and im running it through the linux terminal by using gcc main.c mkdir_creat.c etc. Any help on to why the mkdir function is giving a segmentation fault error would be much appreciated! Thank you!

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

Replace ending of string in C using backwards for loop

I am trying to replace the last part of a string using a for backward for loop iterating for every element of the original string and assigning the first (last elements because I am iterating backwards in the for loop) elements to the string scl = "SCL_10m.tif", and the rest when the counter hits lower than 15, then get all the characters from the string string, and assign them to the newString.
However at the end the result is:
The old string was: S2_2018_08_09_B02_10m.tif
The new string is S2_2018_08_09_B0old string:
Which is different from my expected result:
The new string is S2_2018_08_09_SCL_10m.tif
I don't know what that happened. It supposed to iterate over all the elements of the newString Since it is the same size as the original string. I checked some replace string functions in C, but I wanted to implement something that helps me fast at this particular replace substring in String problem.
Dealing with String in C is very complicated and I am still learning some theory about it, such as: the null Byte and so on. Coming from JavaScript, Python, and Ruby where more of this functions are already implemented in some standard library, I find very hard and at the same time helpful to get the idea of how to implement such algorithms from scratch to deal with specific problems in my code.
I appreciate any idea or hint about what is happening in the code below:
/******************************************************************************
Replace last 11 characters in a longer string
by the values of a smaller (11-char long) string.
*******************************************************************************/
#include <stdio.h>
#include <string.h>
int main()
{
char *string;
string = "S2_2018_08_09_B02_10m.tif";
char *scl;
scl = "SCL_10m.tif";
int length = 0;
int length_scl = 0;
length_scl = strlen(scl);
length = strlen(string);
char newstring[length];
int i;
int cntr = length;
for (i = length; i >= 0; i--)
{
if(cntr > 15){
newstring[i] = scl[i];
cntr--;
}
else if(cntr <= 15)
{
newstring[i] = string[i];
}
}
printf("The old string was: %s\n", string);
printf("The new string is %s:\n", newstring);
return 0;
}
char *func1(char *new, const char *src, const char *repl)
{
size_t src_len, repl_len;
if(src && repl)
{
src_len = strlen(src);
repl_len = strlen(repl);
if(src_len >= repl_len)
{
new[src_len] = 0;
while(repl_len)
{
new[--src_len] = repl[--repl_len];
}
if(src_len)
{
while(--src_len)
{
new[src_len] = src[src_len];
}
}
}
}
return new;
}
char *func2(char *new, const char *src, const char *repl, size_t nchars)
{
//last nchars only (inluding the nul char)
size_t src_len, repl_len;
if(new &&src && repl)
{
new[--nchars] = 0;
src_len = strlen(src);
repl_len = strlen(repl);
if(src_len >= repl_len)
{
while(repl_len && nchars)
{
new[--nchars] = repl[--repl_len];
--src_len;
}
if(src_len && nchars)
{
while(--src_len && --nchars)
{
new[nchars] = src[src_len];
}
}
}
}
return new;
}
int main()
{
char *string = "S2_2018_08_09_B02_10m.tif";
char *repl = "SCL_10m.tif";
char new[256];
printf("func1 - new = \"%s\", src = \"%s\", repl = \"%s\"\n", func1(new, string, repl), string, repl);
printf("func2 - new = \"%s\", src = \"%s\", repl = \"%s\"\n", func2(new, string, repl, 15), string, repl);
printf("func2 - new = \"%s\", src = \"%s\", repl = \"%s\"\n", func2(new, string, "123456789_SCL_10m.tif", 15), string, repl);
return 0;
}

Cannot retrieve all the data from Hashtable

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.

C / parse string, what is the easiest way

I have a string like that:
4;4=3;1=0,2=2,3=1,4=1,5=1;0003013340f59bce000002aaf01620e620198b2240002710;
It is separated into sections by ";" and each section can have one or more key/value pairs like 5=1 and so on, as you can see.
I want to parse it in pure C and I started working with strtok as I am showing in code here:
const wuint8 section_delimiter[] = ";";
const wuint8 field_delimiter[] = ",";
const wuint8 value_delimiter[] = "=";
printf("%s\n",data->msg);
token = strtok(data->msg,section_delimiter);
while(token != NULL) {
indicator = atoi(token);
printf("indicator: %d\n", indicator);
switch(indicator) {
case TYPE_1: {
printf("type: %d\n",TYPE_1);
wuint16 i, headerType, headerSubType;
for(i = 1; i < TP_MAX; i++) {
if(i == atoi(token)) {
token = strtok(NULL,value_delimiter);
headerType = i;
headerSubType = atoi(token);
break;
}
}
break;
}
case TYPE_2: {
printf("type: %d\n",TYPE_3);
break;
}
case TYPE_3: {
printf("type: %d\n",TYPE_3);
break;
}
case TYPE_4: {
printf("type: %d\n",TYPE_4);
break;
}
I am not sure how to do that correctly.
It also gets complicated, because not every string has the same structure, sometimes only one or two sections can be present. E.g.: 3;4=3;1=0,2=2,3=1,4=1,5=1;
Is there a how to do that showing the best and most convenient way?
strtok can't, AFAICR, be used in nested loops like this due to the global state it manages itself.
I suggest parsing each semicolon-delimited part out first, then handling them sequentially - or just implement something akin to strtok for your semicolon case yourself, then happily use strtok in the inner loop.
Using strcspn(). Fixed buffers, results go into global variables. data[] buffer is altered (and thus needs to be writable). YMMV
/*
It is separated into sections by ";" and each section can have one or more
key/value pairs like 5=1 and so on, as you can see. I want to parse it in
pure C and I started working with strtok as I am showing in code here:
*/
char data[] = "4;4=3;1=0,2=2,3=1,4=1,5=1;0003013340f59bce000002aaf01620e620198b2240002710;" ;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct header {
int l;
int r;
} headers[123];
unsigned nheader;
int indicator;
char rest [123];
int tokenise(char * buff);
unsigned tokenise2(struct header *dst, char * buff);
/****************/
int tokenise(char * buff)
{
char *ptrs[14];
unsigned nptr;
unsigned len, pos;
ptrs[nptr=0] = NULL;
for (len = pos=0; buff[pos]; pos += len ) {
len = strcspn(buff+pos, ";");
ptrs[nptr++] = buff+pos;
ptrs[nptr] = NULL;
if (!buff[pos+len] ) break;
buff[pos+len] = 0;
len +=1;
}
if ( nptr> 0 && ptrs[0]) indicator = atoi(ptrs[0]); else indicator = -1;
if ( nptr> 1 && ptrs[1]) nheader = tokenise2 (headers, ptrs[1] ); else nheader = 0;
if ( nptr> 2 && ptrs[2]) nheader += tokenise2 (headers+nheader, ptrs[2] ); else nheader += 0;
if ( nptr> 3 && ptrs[3]) strcpy (rest, ptrs[3]); else rest[0] = 0;
return 0; /* or something useful ... */
}
unsigned tokenise2(struct header *target, char * buff)
{
char *ptrs[123];
unsigned nptr, iptr;
unsigned len, pos;
ptrs[nptr=0] = NULL;
for (len = pos=0; buff[pos]; pos += len ) {
len = strcspn(buff+pos, "," );
ptrs[nptr++] = buff+pos;
ptrs[nptr] = NULL;
if (!buff[pos+len] ) break;
buff[pos+len] = 0;
len +=1;
}
for ( iptr=0; iptr < nptr; iptr++) {
if (! ptrs[iptr] ) break;
len = strcspn(ptrs[iptr], "=" );
if (!len) break;
target[iptr].l = atoi (ptrs[iptr] );
target[iptr].r = atoi (ptrs[iptr]+len+1 );
}
return iptr; /* something useful ... */
}
int main(void)
{
int rc;
unsigned idx;
fprintf(stderr, "Org=[%s]\n", data );
rc = tokenise(data);
printf("Indicator=%d\n", indicator );
for (idx=0; idx < nheader; idx++) {
printf("%u: %d=%d\n", idx, headers[idx].l , headers[idx].r );
}
printf("Rest=%s\n", rest );
return 0;
}

Resources