c appending data at two pointer address - c

I have 2 functions that measure temperature and humidity. Each function returns a pointer to an address containing the data.
uint8_t * get_temperature(int *temperaturelen)
{
memset(htpbuff, 0, sizeof(htpbuff));
int temp_c = readTemperatureC();
htpbuff[0] = 'T';
htpbuff[1] = 'C';
htpbuff[2] = temp_c&0xff;
htpbuff[3] = (temp_c>>8)&0xff;
htpbuff[4] = (temp_c>>16)&0xff;
htpbuff[5] = (temp_c>>24)&0xff;
*temperaturelen = 6;
return (&htpbuff[0]);
}
uint8_t * get_humidity(int *humiditylen)
{
memset(htpbuff, 0, sizeof(htpbuff));
int humidity = readHumidity();
htpbuff[0] = 'R';
htpbuff[1] = '%';
htpbuff[2] = humidity&0xff;
htpbuff[3] = (humidity>>8)&0xff;
htpbuff[4] = (humidity>>16)&0xff;
htpbuff[5] = (humidity>>24)&0xff;
*humiditylen = 6;
return (&htpbuff[0]);
}
I call the functions like this:
tempptr = get_live_temperature(& temp_len);
humptr = get_live_humidity(& hum_len);
I want to appeand the data at each address into a single pointer so that the data at that address would look like TC1234R%1234.
How could I do this?
The reason why is I need to pass this new pointer to a function to transmit the data.
Thanks

Related

ESP32 Arduino allocate and use array of structs in PSRAM

I have a struct like this:
typedef struct {
boolean isExists = false;
uint16_t readBuffer[32] = {0};
uint16_t writeBuffer[13] = {0};
uint16_t ledBrgBuff[9] = {0};
uint16_t address = 0x0000;
uint16_t id = 0x0000;
uint16_t serial = 0x0000;
String kind = "RESERVED";
String name = "RESERVED";
uint16_t readNum = 21;
uint16_t writeNum = 2;
byte read_failCounter = 0;
byte write_failCounter = 0;
byte allowedFails = 10;
long lastWriteFailMSG = 0;
long lastReadFailMSG = 0;
boolean isTesting = false;
boolean criticalOff = false;
boolean onFault = false;
uint8_t data[RESPONSE_COUNT];
} expStruct;
I was using a dynamically allocated array of struct from ram before like this:
expStruct * expanders[MAX_EXPANDER] EXT_RAM_ATTR; // Globally
void fillStructsTest(){
// Fill all the array of structs with data from a json string from the filesystem
JsonArray hwConf = doc.as<JsonArray>();
memset(expanders, 0, sizeof(expanders)); // here I null all the struct in the array
for(byte i = 0; i < hwConf.size(); i ++){
JsonObject module = hwConf[i];
expanders[expCounter] = new expStruct;
expanders[expCounter]->address = module["address"].as<uint16_t>();
expanders[expCounter]->id = module["moduleid"].as<uint16_t>();
expanders[expCounter]->serial = module["serialnr"].as<uint16_t>();
expanders[expCounter]->kind = module["kind"].as<String>();
expanders[expCounter]->name = module["name"].as<String>();
expCounter++;
}
}
That worked pretty well. I could use my array of structs like this:
void useStructTest(){
if( expanders[0] != 0 ){
expanders[0]->name = "Test";
// I can reach every variable inside any of the structs in the array if the value on the index
// is not 0
}
}
Now I want to place this array of structs into PSRAM on my esp32.
I approached it like this:
typedef struct {
boolean isExists = false;
uint16_t readBuffer[32] = {0};
uint16_t writeBuffer[13] = {0};
uint16_t ledBrgBuff[9] = {0};
uint16_t address = 0x0000;
uint16_t id = 0x0000;
uint16_t serial = 0x0000;
String kind = "RESERVED";
String name = "RESERVED";
uint16_t readNum = 21;
uint16_t writeNum = 2;
byte read_failCounter = 0;
byte write_failCounter = 0;
byte allowedFails = 10;
long lastWriteFailMSG = 0;
long lastReadFailMSG = 0;
boolean isTesting = false;
boolean criticalOff = false;
boolean onFault = false;
uint8_t data[RESPONSE_COUNT];
} expStruct;
expStruct *expanders = (expStruct *) ps_malloc(MAX_EXPANDER * sizeof(expStruct));
void fill_PSRAM_StructsTest(){
// Fill all the array of structs with data from a json string from the filesystem
JsonArray hwConf = doc.as<JsonArray>();
// memset(expanders, 0, sizeof(expanders)); // I can't do this now
for(byte i = 0; i < hwConf.size(); i ++){
JsonObject module = hwConf[i];
// expanders[expCounter] = new expStruct; // I can't do this now either.
// also I must replace the -> with . because the compiler erroring me
expanders[expCounter].address = module["address"].as<uint16_t>();
expanders[expCounter].id = module["moduleid"].as<uint16_t>();
expanders[expCounter].serial = module["serialnr"].as<uint16_t>();
expanders[expCounter].kind = module["kind"].as<String>();
expanders[expCounter].name = module["name"].as<String>();
expCounter++;
}
}
Somewhere here my ESP crashing without a meaningful serial output, which is this:
Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400ec9a7 PS : 0x00060630 A0 : 0x80090915 A1 : 0x3ffdaee0
A2 : 0x00000000 A3 : 0x3f80afdc A4 : 0x00000000 A5 : 0x3ffc25fc
A6 : 0x00000000 A7 : 0x3ffdaf64 A8 : 0x800ec9a2 A9 : 0x3ffdaeb0
A10 : 0x00000001 A11 : 0x3f40203a A12 : 0x3ffdafd0 A13 : 0xf655c6f4
A14 : 0x3ffdadc0 A15 : 0x00000005 SAR : 0x00000010 EXCCAUSE: 0x0000001d
EXCVADDR: 0x0000006e LBEG : 0x4008d6b1 LEND : 0x4008d6c1 LCOUNT : 0xfffffff7
ELF file SHA256: 0000000000000000
Backtrace: 0x400ec9a7:0x3ffdaee0 0x40090912:0x3ffdb000
#0 0x400ec9a7:0x3ffdaee0 in mbusTask(void*) at lib/modbus-esp8266-3.0.6/src/Modbus.h:238
(inlined by) mbusTask(void*) at src/Own_Headers/busCommunication.h:559
#1 0x40090912:0x3ffdb000 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Rebooting...
ets Jul 29 2019 12:21:46
Should I allocate every index again in a function or what should I do to use it normally like before?
sorry for my english, you can't use String in PSRAM (dynamic)
you use: char name[100];
no String !!!
and ... copy from JSON to stuct :-)
strcpy(expanders[expCounter].name,
module["name"].as < string > ().c_str());
To move a ArduinoJsonDocument into PSRAM one needs to do it like so:
struct SpiRamAllocator {
void* allocate(size_t size) {
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
}
void deallocate(void* pointer) {
heap_caps_free(pointer);
}
void* reallocate(void* ptr, size_t new_size) {
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
}
};
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
see here for a more detailed info.
To move any variable into PSRAM memory space one needs to declare it as below for the case of a uint16_t:
uint16_t* p_buffer_a = (uint16_t*) heap_caps_malloc(307200, MALLOC_CAP_SPIRAM );
where 307200 is the uint16_t byte size memory allocation to that specific variable p_buffer_a. The maximum element size for this array can be determined like this:
sizeof(p_buffer_a)/sizeof(uint16_t)
Mind you if one needs / wants to use Strings, it needs to rebuild the String class to accommodate PSRAM memory allocation.
Another way to move variable data into PSRAM is by wrapping it in a typedef struct.To allocate a buffer dynamically at runtime like the one below, one can declare it as follows:
typedef struct{
int len;
uint8_t buff[INTERRUPT_BUFFER_SIZE];
} Buffer;
this particular one stores a variable array named buff with element size of INTERRUPT_BUFFER_SIZE. Next is needs to declare a variable name that is stored directly into PSRAM:
Buffer *bufferA = (*Buffer) heap_caps_malloc( sizeof(Buffer), MALLOC_CAP_SPIRAM );
Followed by its initialization in the setup function
//setup() initialization
void setup(){
bufferA = new Buffer();
...
}
Its usage through the code is made this way "bufferA->field" instead of the regular traditional way "bufferA.field".

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!

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.

realloc array of struct inside another struct

I'm working on a project where the goal is to create automatons.
Automatons are defined by a struct :
typedef struct {
int num_states;
int initial_state;
State * states;
} Automaton;
And State is another struct defining arcs between states:
typedef struct {
int num_arcs;
bool is_final;
Arc * arcs;
} State;
typedef struct {
int symbol;
int destination;
} Arc;
I create an automaton with malloc as such :
Automaton* create_automaton(void) {
Automaton * a = (Automaton *)malloc(sizeof(Automaton));
assert(a != NULL);
a->initial_state = UNDEFINED;
a->num_states = 0;
a->states = NULL;
return a;
}
So then I want to take 2 Automatons with states and arcs created with these functions :
int add_state(Automaton* a) {
State* state = (State *)realloc(a->states, (a->num_states + 1) * sizeof(State));
if(state == NULL)
exit(EXIT_FAILURE);
a->states = state;
a->states[a->num_states].num_arcs = 0;
a->states[a->num_states].is_final = FALSE;
a->states[a->num_states].arcs = NULL;
return a->num_states++;
}
void add_arc(Automaton* a, int from, int to, int symbol) {
if(from >= a->num_states || to >= a->num_states)
exit(EXIT_FAILURE);
Arc * arc = (Arc *)realloc(a->states[from].arcs, (a->states[from].num_arcs + 1) * sizeof(Arc));
if(arc == NULL)
exit(EXIT_FAILURE);
a->states[from].arcs = arc;
a->states[from].arcs[a->states[from].num_arcs].destination = to;
a->states[from].arcs[a->states[from].num_arcs].symbol = symbol;
a->states[from].num_arcs++;
}
I want to combine these 2 Automatons in one so I wrote this function:
Automaton* append_automaton(Automaton * a1, Automaton * a2)
{
Automaton * a = copy_automaton(a1);
int i = 0;
for(i = 0; i < a2->num_states; i++)
{
add_state(a);
a->states[a1->num_states + i] = a2->states[i];
for(j = 0;j<a->states->num_arcs;j++)
{
a->states[i].arcs[j].destination =+ a2->num_states;
}
}
a->initial_state = a1->initial_state;
return a;
}
However I can create the Automaton, add states and arcs to it without any problem, when i try to merge them together with append_automaton I get a segmentation fault when in add_state() I realloc State to fit one more state in the new automaton.
So my question is the following : Why is realloc giving me a segmentation fault when in this function (append_automaton) althought it works perfectly outside of it?
PS: copy_Automaton() does indeed overwrite the create_Automaton() so I removed the line: Automaton * a = create_automaton() in append_automaton()
And here is copy_automaton():
Automaton* copy_automaton(Automaton* a) {
int i = 0;
Automaton * cp_a = malloc(sizeof(Automaton));
cp_a->states = malloc(sizeof(a->states));
for(i = 0; i < a->num_states; i++)
{
cp_a->states[i].arcs = malloc(sizeof(a->states[i].arcs));
cp_a->states[i] = a->states[i];
}
cp_a->num_states = a->num_states;
cp_a->initial_state = a->num_states;
//memcpy(a, cp_a, sizeof(Automaton));
return cp_a;
}
The problem I see is your are updating a->num_states after the for cycle. However a->num_states it is used inside the cycle in the function add_state(a);
You need to put (a->num_states)++ inside the loop.

Increasing structure size and then resetting them back to original size and increase size again

I am new to C but I am currently working on a C program which I am having an issue with relating to structures and memory allocation.
What I have in my code is a permanent while loop which will break out of when a certain condition is met. Within this while loop it checks the database and has a while loop to loop round the MySQL rows.
When the program first loads, it creates 3 structures, one of the structures also containing a linked list and initialised to be a size of 100.
As my program loops through the MySQL rows it checks whether 100 records have been added, and if so, then does a realloc to increase the size by another 100 rows. When I have looped through all of the MySQL rows it then returns to main while loop (the never ending loop) and NULL's the structures and then initialises them again to be 100 rows and starts all over again.
The problem I am having, is once it does the first complete loop through all of the mysql rows and returns to the main never ending loop and the structures are reinitialised back to be a size of 100, on the 17th row my program segfaults. When I inspect everything in GDB the structure at index 17 comes up saying that the certain elements within the structure are out of bounds.
Below is the definition for the structure I am having the issue with.
typedef struct CallLogSearchDataStruct
{
char * date;
char * time;
char * bParty;
char * aParty;
float duration;
char * cleardownCause;
struct CallLogSearchOutboundStruct * outboundLegs;
} callLogSearchDataStruct;
Below is how the structure initially get set up when the program first runs
callLogSearchData = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchDataStruct));
callLogSearch = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchResultStruct));
switches = calloc(INITIAL_CALL_STRUCT_SIZE, sizeof(switchIDStructure));
INITIAL_CALL_STRUCT_SIZE is equal to 100.
Below is the code for how the reallocateStructures function is called. This reallocates the structures by adding another 100 in size to the original size.
if (reallocateStructures(&callLogSearch, &callLogSearchData, &switches, &timesStructHasBeenReallocated, currentStructIndexValue, dataRow) == 0)
{
//Structures have been reallocated so reset the index
currentStructIndexValue = 0;
}
Below is the actual code for the reallocating of the structures
int reallocateStructures(callLogSearchResultStruct **callLogSearch, callLogSearchDataStruct ** callLogSearchData,
switchIDStructure ** switches, int *timesStructHasBeenReallocated, int currentStructIndexValue,
int dataRow)
{
int INITIAL_CALL_STRUCT_SIZE = 100;
int currentSize = 0;
int newSize = 0;
int initFromIndex = 0;
callLogSearchResultStruct * callLogSearchTemp;
callLogSearchDataStruct * callLogSearchDataTemp;
switchIDStructure * switchesTemp;
printf("Current Struct Index Value: %i\n", currentStructIndexValue);
if (currentStructIndexValue >= INITIAL_CALL_STRUCT_SIZE) {
printf("REALLOCATING STRUCTURES");
currentSize = currentStructIndexValue * *timesStructHasBeenReallocated;
newSize = currentSize + INITIAL_CALL_STRUCT_SIZE;
*timesStructHasBeenReallocated = *timesStructHasBeenReallocated + 1;
callLogSearchTemp= (callLogSearchResultStruct*)realloc(*callLogSearch, (newSize * sizeof(callLogSearchResultStruct)));
callLogSearchDataTemp = (callLogSearchDataStruct*)realloc(*callLogSearchData, (newSize * sizeof(callLogSearchDataStruct)));
switchesTemp = (switchIDStructure*)realloc(*switches, (newSize * sizeof(switchIDStructure)));
/**callLogSearchData = realloc(*callLogSearchData, newSize * sizeof (callLogSearchDataStruct));
*callLogSearch = realloc(*callLogSearch, newSize * sizeof (callLogSearchResultStruct));
*switches = realloc(*switches, newSize * sizeof (switchIDStructure));
*/
for (initFromIndex = currentSize; initFromIndex < newSize; initFromIndex++) {
callLogSearchDataTemp[initFromIndex].aParty = NULL;
callLogSearchDataTemp[initFromIndex].bParty = NULL;
callLogSearchDataTemp[initFromIndex].cleardownCause = NULL;
callLogSearchDataTemp[initFromIndex].date = NULL;
callLogSearchDataTemp[initFromIndex].duration = 0;
callLogSearchDataTemp[initFromIndex].outboundLegs = NULL;
callLogSearchDataTemp[initFromIndex].time = NULL;
callLogSearchTemp[initFromIndex].date = NULL;
callLogSearchTemp[initFromIndex].dRowIndex = dataRow;
switchesTemp[initFromIndex].switchID = NULL;
if (initFromIndex == newSize - 1)
{
printf("debugging here\n");
}
}
*callLogSearch = callLogSearchTemp;
*callLogSearchData = callLogSearchDataTemp;
*switches = switchesTemp;
return 0;
}
else
{
return 1;
}
}
Below is the code where after it has looped through all of the MySQL rows the structures are then reset and re-initialised to be a size of 100.
//Check if function has looped round already and if so reset all structures
if (dataRow > -1)
{
numberOfTimesEverythingHasReset++;
callLogSearchData = NULL;
callLogSearch = NULL;
switches = NULL;
callLogSearchData = realloc(callLogSearchData, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
callLogSearch = realloc(callLogSearch, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
switches = realloc(switches, INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//initialiseNewStructure(&callLogSearch, &callLogSearchData, &switches);
//callLogSearchData = (callLogSearchDataStruct*)realloc(callLogSearchData, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
//callLogSearch = (callLogSearchResultStruct*)realloc(callLogSearch, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
//switches = (switchIDStructure*)realloc(switches, INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//Initialise all elements within structures
for (initFromIndex = INITIAL_CALL_STRUCT_SIZE; initFromIndex < INITIAL_CALL_STRUCT_SIZE; initFromIndex++)
{
callLogSearchData[initFromIndex].aParty = NULL;
callLogSearchData[initFromIndex].bParty = NULL;
callLogSearchData[initFromIndex].cleardownCause = NULL;
callLogSearchData[initFromIndex].date = NULL;
callLogSearchData[initFromIndex].duration = 0;
callLogSearchData[initFromIndex].outboundLegs = NULL;
callLogSearchData[initFromIndex].time = NULL;
callLogSearch[initFromIndex].date = NULL;
callLogSearch[initFromIndex].dRowIndex = dataRow;
}
timesStructHasBeenReallocated = 1;
currentSize = 0;
}
currentStructIndexValue = 0;
I'm not sure why when it enters the if statement the first time to reset the structures back to a size of 100, after the 17 MySQL row the memory is then out of bounds so I segfault.
Thanks for any help you can provide.
UPDATE
I have fixed the issue with the for loop as per #Rohan answer but I am now getting a slightly different issue.
I am now getting a different area when trying to add data to the structures but I am not sure if the structures are anything to do with it as it seems to be the MySQL array having an out of bounds issue now causing a seg fault.
The line where it is failing is
callLogSearchData[dataRow].bParty = strdup(rowReport[bPartyColIndex]);
When I inspect rowReport in GDB it seems to have garbage inside it and at the 7th index (bPartyColIndex is at index 9) I start to see the out bounds error.
rowReport is assigned at each time the loop for each mysql row as shown in the code below
sqlLen = asprintf(&sql, "SELECT Tmp.SwitchID, Tmp.CorrelationID, SeizeUTC as Date, "
"SeizeUTC as Time, Direction, ACMToAns/100 as ACMToAns, Duration/100 as Duration, "
"CleardownCause, AParty, Tmp.BParty FROM TMP_Log AS Tmp ORDER BY SeizeUTC, "
"Tmp.SwitchID, Tmp.CorrelationID, Direction, SeizeCSec LIMIT %i, %i",
index, count);
SL_DebugAll(DBG_INFO, sql);
if ((mysql_real_query(HandleDB, sql, sqlLen))) return 1;
resultReport = mysql_store_result(HandleDB);
if (mysql_num_rows(resultReport) == 0 || index > atoi(limit))
{
SL_DebugAll(DBG_INFO, "Data retrieval for call log complete");
break;
}
else
{
numRows = mysql_num_rows(resultReport);
swID = -1;
corrID = -1;
dataRow = -1;
if (numRows > 0)
{
maxTargets = 1;
}
audioRow = mysql_fetch_row(audioResult);
sspSwitchID = atoi(audioRow[switchIDColIndex]);
sspCorrID = atoi(audioRow[correlationIDColIndex]);
inbound_counter = 0;
while (rowReport = mysql_fetch_row(resultReport))
In last code section of yours you have
if (dataRow > -1)
{
numberOfTimesEverythingHasReset++;
callLogSearchData = NULL;
callLogSearch = NULL;
switches = NULL;
callLogSearchData = realloc(callLogSearchData,
INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
callLogSearch = realloc(callLogSearch,
INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
switches = realloc(switches,
INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//Initialise all elements within structures
for (initFromIndex = INITIAL_CALL_STRUCT_SIZE;
initFromIndex < INITIAL_CALL_STRUCT_SIZE;
initFromIndex++)
{
....
You are setting callLogSearchData to NULL so reallocating is not relevant.
And you are allocating for INITIAL_CALL_STRUCT_SIZE number of elements, but your for loop counter starts from INITIAL_CALL_STRUCT_SIZE so effectively for loop does not execute.
I've managed to find out what the issue, its a pretty basic mistake unfortunately.
Because of where the code was crashing, I thought it had to be something related to the way I was re-initialised the structure, maybe because of the way I was using pointers.
However, this was not the case instead, instead, somewhere else in the code I was adding some data to one of the structures using an index called fileRow. Each time a value was added to the structure I incremented fileRow however I forgot to reset back to 0 when I realloced the structures, so when I realloced the structures to be of size 100, I was inserting into the structure of where fileRow was which was set to 1300 so each time I looped round I smashed up the memory until it segfaulted.
Thanks for your help and suggestions.

Resources