I am trying to write a C program that generates R files that solve systems of linear equations. In main, I have six nested for loops to get every iteration of where the coefficients are integers 0 - 9:
ax + by + c = dx + ey + f
a_2x + b_2y + c_2 = d_2x + e_2y + f
Each equation is a array of 6 integer coefficients. I set the values of the coefficients in my main function before passing it to generateContentForSystems.
However, my print statement returns:
value of numx:-000-0 value of numy:000-0 value of numz:00-0 value of numx_2:0-0 value of numy_2:-0 value of numz_2:0
I believe this is because of bad pointer arithmetic. I am now trying to and from a pointer to an array (in main) and have an array of arrays.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "scaffold.c"
void * generateContentForSystems(int * row1, int * row2) {
static int index = 0;
int x = row1[0] - row1[3];
int y = row1[1] - row1[4];
int z = row1[5] - row1[2];
int x_2 = row2[0] - row2[3];
int y_2 = row2[1] - row2[4];
int z_2 = row2[5] - row2[2];
int prod1 = x * y_2;
int prod2 = x_2 * y;
int determinant = prod1 - prod2;
if (determinant != 0) {
printf("the value of determinant: %d", determinant);
char * error1;
char Q[1000];
strcpy(Q, "emake <- function(){\noptions(\"warn\"=-1)\ne <- 0\nfor (n in 0:2000){\ne <- e+ 1/(factorial(n))\n}\nreturn(e)\n}\ne <- emake()\n");
char numx[1];
char numy[1];
char numz[1];
char numx_2[1];
char numy_2[1];
char numz_2[1];
sprintf(numx, "%d", x);
sprintf(numy, "%d", y);
sprintf(numz, "%d", z);
sprintf(numx_2, "%d", x_2);
sprintf(numy_2, "%d", y_2);
sprintf(numz_2, "%d", z_2);
//debug:
printf("value of numx:%s value of numy:%s value of numz:%s value of numx_2:%s value of numy_2:%s value of numz_2:%s", numx, numy, numz, numx_2, numy_2, numz_2);
strcat(Q, "A = array(c(");
strcat(Q, numx);
strcat(Q, ", ");
strcat(Q, numx_2);
strcat(Q, ", ");
strcat(Q, numy);
strcat(Q, ", ");
strcat(Q, numy_2);
strcat(Q, "), dim = c(2,2,1))\n");
strcat(Q, "b = c(");
strcat(Q, numz);
strcat(Q, ", ");
strcat(Q, numz_2);
strcat(Q, ")\n");
strcat(Q, "solve(A[,,1],b)\n");
char filename[100];
char snum[5];
itoa(index, snum);
index++;
strcpy(filename, "practice/");
strcat(filename, snum);
strcat(filename, ".R");
FILE * F = fopen(filename, "w");
fputs(Q, F);
fclose(F);
char path[1024];
char command[300];
strcpy(command, "Rscript ");
strcat(command, "practice/");
debug("After Rscript formation");
strcat(command, snum);
strcat(command, ".R");
FILE * fp = popen(command, "r");
if (!fp) { //validate file is open
return NULL;
}
while (fgets(path, sizeof(path) - 1, fp) != NULL) {
debug("in Primary While Loop");
fflush(stdout);
printf("the solution: %s", path);
if (strstr(path, ".") > strstr(path, "with absolute error") || strstr(path, ".5 ") != NULL) {
printf("answer was accepted");
}
}
}
}
int main() {
int arrayIndexes = 0;
int ** myArray = malloc(1 * sizeof( * myArray));
for (int a = 0; a < 10; a++) {
for (int b = 0; b < 10; b++) {
for (int c = 0; c < 10; c++) {
for (int d = 0; d < 10; d++) {
for (int e = 0; e < 10; e++) {
for (int f = 0; f < 10; f++) {
myArray[arrayIndexes] = malloc(6 * sizeof(int));
myArray[arrayIndexes][0] = a;
myArray[arrayIndexes][1] = b;
myArray[arrayIndexes][2] = c;
myArray[arrayIndexes][3] = d;
myArray[arrayIndexes][4] = e;
myArray[arrayIndexes][5] = f;
if (arrayIndexes > 0) {
for (int i = 0; i < arrayIndexes; i++) {
generateContentForSystems(myArray[arrayIndexes], myArray[i]);
}
}
++arrayIndexes;
myArray = realloc(myArray, (arrayIndexes + 1) * sizeof( * myArray));
}
}
}
}
}
}
for (int n = 0; n = arrayIndexes; n++) {
free(myArray[n]);
}
free(myArray);
return 0;
}
Your number strings are not long enough:
char numx[1];
char numy[1];
char numz[1];
char numx_2[1];
char numy_2[1];
char numz_2[1];
A string consists of a sequence of characters plus a null terminating byte. So even a single digit needs an array size of at least 2. When you use sprintf to write the text representation of a number to one of these arrays you write past the end of the array. This invokes undefined behavior.
These arrays need to be large enough to accommodate whatever value you may pass in, including a negation sign if needed.
char numx[10];
char numy[10];
char numz[10];
char numx_2[10];
char numy_2[10];
char numz_2[10];
Related
I am not able to debug what is going on. The code seems correct yet I am new to pointers to pointers, and here there are 4 in series.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
return *(*(*(document + n - 1) + m - 1) + k - 1);
}
char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) {
return (*(*(document + m - 1) + k - 1));
}
char ***kth_paragraph(char ****document, int k) {
return *(document + k - 1);
}
char ****get_document(char *text) {
/* allocating memory */
int len = strlen(text);
/* allocate memory for each component first */
char ****document = malloc(sizeof(char ***));
char ***paragraph = malloc(sizeof(char **));
char **sentence = malloc(sizeof(char *));
char *word = malloc(sizeof(char) * 1024);
/* connect all the components to point in the sequence that is required */
*document = paragraph;
*paragraph = sentence;
*sentence = word;
/* declare some numbers as iterators for the words, sentences,etc. */
int parano = 0;
int sentno = 0;
int wordno = 0;
int charno = 0;
/* now iterate over the text filling and expanding the document at the same time */
/*----------------------------------------------------------------------------------------------------*/
/* feeding data in those spaces */
for (int i = 0; i < len; i++) {
if (text[i] == ' ') {
/* wrapping the current word, that is, resizing to len + 1 */
char *current_word = *(*(*(document + parano) + sentno) + wordno);
current_word = realloc(current_word, strlen(current_word) + 1);
/* resizing the current sentence to add another word*/
char **current_sentence = (*(*(document + parano) + sentno));
current_sentence = realloc(current_sentence, sizeof(char *) * (wordno + 2));
wordno++;
charno = 0;
/* allocating space to that new char * / word that has been created in the same sentence */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
}
else if (text[i] == '.') {
/* wrapping of the current word has to be done anyways */
char *current_word1 = *(*(*(document + parano) + sentno) + wordno);
current_word1 = realloc(current_word1, strlen(current_word1) + 1);
charno = 0;
if (text[i + 1] != '\n') {
/* the paragraph does not change, and the sentence ends */
/* resize that paragraph for adding another sentence */
char ***current_para = *(document + parano);
current_para = realloc(current_para, sizeof(char **) * (sentno + 2));
sentno++;
wordno = 0;
/* allocating word to that sentence */
*(*(document + parano) + sentno) = malloc(sizeof(char *));
/* allocating space for that word */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
} else {
/* if this is the last sentence of this paragraph*/
wordno = 0;
charno = 0;
sentno = 0;
}
}
else if (text[i] == '\n') {
/* paragraph has changed */
/* add another paragraph to the document */
document = realloc(document, sizeof(char ***) * (parano + 2));
parano++;
/* add sentence to that paragraph */
(*(document + parano) ) = malloc(sizeof(char **));
/* add a word to that paragrapgh */
(*(*(document + parano) + sentno)) = malloc(sizeof(char *));
/* allocate space for that word */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
} else {
scanf("%c", *(*(*(document + parano) + sentno) + wordno) + charno);
printf("%c\n", **(*(*(document + parano) + sentno) + wordno) + charno);
charno++;
}
}
return document;
}
char *get_input_text() {
int paragraph_count;
scanf("%d", ¶graph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char *returnDoc = (char *)malloc((strlen(doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
void print_word(char *word) {
printf("%s", word);
}
void print_sentence(char **sentence) {
int word_count;
scanf("%d", &word_count);
for (int i = 0; i < word_count; i++) {
printf("%s", sentence[i]);
if (i != word_count - 1)
printf(" ");
}
}
void print_paragraph(char ***paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(*(paragraph + i));
printf(".");
}
}
int main() {
char *text = get_input_text();
char ****document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3) {
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
char *word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
print_word(word);
}
else if (type == 2) {
int k, m;
scanf("%d %d", &k, &m);
char **sentence = kth_sentence_in_mth_paragraph(document, k, m);
print_sentence(sentence);
} else {
int k;
scanf("%d", &k);
char ***paragraph = kth_paragraph(document, k);
print_paragraph(paragraph);
}
printf("\n");
}
}
this is one of the questions on Hackerrank for the C language.
link to the question
hacker rank question
my profile
shows aborted, realloc invalid size. I couldn't find anything for the last 2 days.
inputs for the problem
2
Learning C is fun.
Learning pointers is more fun.It is good to have pointers.
3
1 2
2
5
6
2 1 1
4
3 1 1 1
expected output
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
When processing regular characters (final else clause) you read additional input instead of operating over text, i.e. instead of:
scanf("%c", &document[parano][sentno][wordno][charno]);
printf("%c\n", document[parano][sentno][wordno][charno]);
charno++;
you want to do:
document[parano][sentno][wordno][charno++] = text[i];
By the time we hit text[i] == ' ' for the first time the value of ***document is "3\n1 2\n2\n" but you wanted it to be "Learning".
(not fixed) When processing a word (`text[i] == ' ') you expand current word, yet, you hard-code 1000 when you allocate it initially so this doesn't make sense. Be consistent.
parano, sentno, wordno, charno is indices but same suggest they are counts. It's not wrong just confusing and why you have to wordno + 2 when relloc'ing.
Terminate words with `\0'.
When you process ' ' you add another word which you may or may not need which is fine. But when process a '.' you look ahead to the following letter is a \n or not. Be consistent. If you look ahead then you need to check that i + 1 < len, and it's fragile, say, there is a stray space before the \n.
(not fixed) Memory leaks. As the size of the sub-elements (paragraph, sentences and words) are private implementation details of get_document() you will have refactor the code to make those available. I suggest:
struct document {
char ****document;
size_t paragraphs;
size_t sentences;
size_t words;
}
(not fixed) Deduplicate. Similar to the print functions, create a allocation function per type.
(not fixed, really) get_input_text(). You split the into paragraphs then concatenate everything again into a local variable then copy it into a dynamically allocated variable:
char *str = malloc(BUFFER_LEN);
for(size_t i = 0, l = 0; l < lines && i + 1 < BUFFER_LEN; i += strlen(str + i)) {
int rv = fgets(str + i, BUFFER_LEN - i, stdin);
if(!rv) {
// handle error
break;
}
}
return s;
(not fixed) Separate i/o from processing. This simplifies testing and it makes it easier to figure out what is going on. In main(), you read a query type then 1 to 3 numbers. scanf()` tells you how many items where read so you simply do. As you don't use the kth_ functions for anything else just combine then with print_ funci
int n = scanf("%d %d %d %d", &type, &p, &s, &w);
switch(type) {
case 1:
if(n != 2) {
// handle error
}
print_paragraph(document, p);
break;
...
}
(not fixed) Add error checks for the remainingmalloc(), strdup() etc.
Don't hard-code magic values (1000). I introduced the constant WORD_LEN but you also have MAX_CHARACTERS which is kinda the same thing.
(not fixed) Consider using char *s = strpbrk(text + i, " .\n") to copy a word at a time. It will simplify \0 handling, and likely to be faster than walking the text a byte at a time, i.e. i += s - text + i, just handle the s == NULL special case.
valgrind is now happy other than leaks (see above):
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
#define WORD_LEN 1000
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int p, int s, int w) {
return document[p - 1][s - 1][w - 1];
}
char **kth_sentence_in_mth_paragraph(char ****document, int p, int s) {
return document[p - 1][s - 1];
}
char ***kth_paragraph(char ****document, int p) {
return document[p - 1];
}
char ****get_document(char* text) {
char ****document = malloc(sizeof ***document);
*document = malloc(sizeof **document);
**document = malloc(sizeof *document);
***document = malloc(WORD_LEN);
/* declare some numbers as iterators for the words, sentences,etc.*/
int parano = 0;
int sentno = 0;
int wordno = 0;
int charno = 0;
/* now iterate over the text filling and expanding the document at the same time*/
/*----------------------------------------------------------------------------------------------------*/
/* feading data in those spaces*/
size_t len = strlen(text);
for (size_t i = 0; i < len; i++) {
switch(text[i]) {
case ' ': {
document[parano][sentno][wordno][charno] = '\0';
wordno++;
char **words = realloc(
document[parano][sentno],
(wordno + 1) * sizeof *document[parano][sentno]
);
if(!words) {
printf("realloc of words failed\n");
exit(1);
}
document[parano][sentno] = words;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
case '.': {
document[parano][sentno][wordno][charno] = '\0';
sentno++;
char ***sentences = realloc(
document[parano],
(sentno + 1) * sizeof *document[parano]
);
if(!sentences) {
printf("realloc of sentences failed\n");
exit(1);
}
document[parano] = sentences;
document[parano][sentno] = malloc(sizeof **document);
wordno = 0;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
case '\n': {
document[parano][sentno][wordno][charno] = '\0';
parano++;
char ****paragraphs = realloc(
document,
(parano + 1) * sizeof *document
);
if(!paragraphs) {
printf("realloc of paragraphs failed\n");
exit(1);
}
document = paragraphs;
document[parano] = malloc(sizeof ***document);
sentno = 0;
document[parano][sentno] = malloc(sizeof **document);
wordno = 0;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
default: // character
document[parano][sentno][wordno][charno++] = text[i];
}
}
return document;
}
char *get_input_text() {
int paragraph_count;
scanf("%d", ¶graph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS];
char doc[MAX_CHARACTERS];
memset(doc, 0, sizeof doc);
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
return strdup(doc);
}
void print_word(char *word) {
printf("%s", word);
}
void print_sentence(char **sentence) {
int word_count;
scanf("%d", &word_count);
for(int i = 0; i < word_count; i++){
print_word(sentence[i]);
if(i + 1 != word_count)
printf(" ");
}
}
void print_paragraph(char ***paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(paragraph[i]);
printf(".");
}
}
int main() {
char *text = get_input_text();
char ****document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
switch(type) {
case 1: {
int p;
scanf("%d", &p);
print_paragraph(kth_paragraph(document, p));
break;
}
case 2: {
int p, s;
scanf("%d %d", &p, &s);
print_sentence(kth_sentence_in_mth_paragraph(document, p, s));
break;
}
case 3: {
int p, s, w;
scanf("%d %d %d", &p, &s, &w);
print_word(kth_word_in_mth_sentence_of_nth_paragraph(document, p, s, w));
break;
}
default:
printf("error\n");
}
printf("\n");
}
free(text);
}
Output as expected:
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
Btw, a whole different way of solving this is problem is keep the original input (text) then write functions to directly extract a paragraph, sentence or word from that string. If you input is huge then create an index, say, (paragraph, sentence, word) to &text[i].
finally did it.
a big thanks to #allanwind for your support
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
return *(*(*(document + n - 1) + m - 1) + k - 1);
}
char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) {
return (*(*(document + m - 1) + k - 1));
}
char ***kth_paragraph(char ****document, int k) {
return *(document + k - 1);
}
char ****get_document(char *a)
{
int len = strlen(a);
char ****document = malloc(sizeof(char ***) * MAX_PARAGRAPHS);
int parano = 0;
char ***paragraph = malloc(sizeof(char **) * MAX_CHARACTERS);
int sentno = 0;
char **sentence = malloc(sizeof( char *) * MAX_CHARACTERS);
int wordno = 0;
char *word = malloc(sizeof(char ) * MAX_CHARACTERS);
int charno = 0;
for (int i = 0; i < len; i++)
{
/* after this way, try to learn switch conditionals*/
if (a[i] == ' ')
{
/* if find a space, that is there are more words within the same sentence*/
/* close the word*/
word[charno] = '\0';
/* add the word to the sentence*/
sentence[wordno] = word;
wordno++;
charno = 0;
/* create another word*/
char *tmp = malloc(sizeof(char) * MAX_CHARACTERS);
/* if the word got space without errors,*/
if (tmp != NULL)
{
word = tmp;
}
}
else if (a[i] == '.')
{
// terminate the word
word[charno] = '\0';
// add word to the sentence
sentence[wordno] = word;
wordno = 0;
charno = 0;
// add sentence to paragraph
paragraph[sentno] = sentence;
if (i != len - 1)
{
sentno++;
// allocate space for new sentence, as it is not the end
char **tmp1 = malloc(sizeof(char *) * MAX_CHARACTERS);
if (tmp1 != NULL)
{
sentence = tmp1;
}
// allocate space for new word
char *tmp2 = malloc(sizeof(char) * MAX_CHARACTERS);
if (tmp2 != NULL)
{
word = tmp2;
}
}
else
{
document[parano] = paragraph;
}
}
else if (a[i] == '\n')
{
// add paragraph to the document
document[parano] = paragraph;
parano++;
// allocate memory for another paragraph
char ***tmp3 = malloc(sizeof(char **) * MAX_CHARACTERS);
if (tmp3 != NULL)
{
paragraph = tmp3;
}
charno = 0;
wordno = 0;
sentno = 0;
}
else
{
/* step 1 read the text into the word char by char*/
word[charno] = a[i];
charno++;
}
}
return document;
}
char* get_input_text() {
int paragraph_count;
scanf("%d", ¶graph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
void print_word(char* word) {
printf("%s", word);
}
void print_sentence(char** sentence) {
int word_count;
scanf("%d", &word_count);
for(int i = 0; i < word_count; i++){
printf("%s", sentence[i]);
if( i != word_count - 1)
printf(" ");
}
}
void print_paragraph(char*** paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(*(paragraph + i));
printf(".");
}
}
int main()
{
char* text = get_input_text();
char**** document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3){
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
char* word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
print_word(word);
}
else if (type == 2){
int k, m;
scanf("%d %d", &k, &m);
char** sentence = kth_sentence_in_mth_paragraph(document, k, m);
print_sentence(sentence);
}
else{
int k;
scanf("%d", &k);
char*** paragraph = kth_paragraph(document, k);
print_paragraph(paragraph);
}
printf("\n");
}
}
I am a beginner at coding and am currently in a course for this. I have been asked to produce a program that has a special function to convert the timestamps in a file into something that can be sorted from earliest to latest based on a numerical value. These would be imported from a file into an array. Some points of the assignment are:
The array of strings should be allocated dynamically to minimise the amount of memory used.
Create a function called timeStampToSeconds() that converts a timestamp string to a long int, which represents the number of seconds elapsed since 01/01/2000 00:00:00.
Your code will need to check that each character is a valid number between 0 and 9, ignoring formatting characters ('/', ' ', ':', '-') and convert the characters to their equivalent integers before being used to calculate the number of seconds elapsed since the above starting point.
I have included my code but am wondering if anyone has any pointers to help me on point 2 & 3? I have started with trying to implement point 3 with the strtok function, but I think I may be way off on this.Curently my function prototype is not doing what I had hoped for this.
Any advice would be much appreciated.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 50
void timeStampToSeconds(char array[]);
int main(void)
{
char array[50][20];
char input[10], filename[] = "Timestamps", outputfile[40], file_ext[4] = ".dat";
int i = 0, n = 0, j, x = 0, y = 0, o = 0;
double datetime = 0;
while (*input != *filename) {
printf("\nPlease enter the names of the required Input file: \n");
scanf("%s", input);
if (*input == *filename) {
printf("Input accepted!\n");
}
else printf("File name not found.Please try again!\n");
}
printf("Please enter the name of the sorted Output file to be created: \n");
scanf("%s", &outputfile);
strncat(&outputfile, &file_ext, 4); /*appends file extension characters to outputfile
variable characters*/
FILE* Ptr = NULL;
FILE* cfPtr = (char*)malloc(100 * sizeof(char));
if ((cfPtr = fopen("Timestamps.dat", "r")) == NULL) {
printf("File could not be opened\n");
}
while (!feof(cfPtr))
{
for (i = 0; i < 50; ++i)
{
for (j = 0; j < 20; ++j)
{
array[x][j] = fgetc(cfPtr);
y++;
}
x++;
}
}
fclose(cfPtr);
timeStampToSeconds(array);
if ((Ptr = fopen(outputfile, "w")) == NULL) {
printf("File could not be opened\n");
}
fwrite(array, sizeof(char), sizeof(array), Ptr);
fclose(Ptr);
return 0;
}
void timeStampToSeconds(char array[])
{
array;
long int n = 0, j = 0;
const char a[2] = "/"; const char b[2] = "-";
const char c[2] = ":";
char* token; char* token2; char *token3;
for (int i = 0; i < SIZE - 1; ++i) {
token = strtok(array, a);
while (token != NULL) {
token = strtok(NULL, a);
}
token2 = strtok(token, b);
while (token2 != NULL) {
token2 = strtok(NULL, b);
}
token3 = strtok(token2, c);
while (token3 != NULL) {
token3 = strtok(NULL, c);
}
token3 = array;
}
for (int i = 0; i < SIZE - 1; ++i) {
n = atol(array[i]);
array[i] = n;
}
}
I was able to print in a file but its now stuck in one same result for my %.4f. The arrays is not taking the info from my getinfo function and note letting me print the right answer. I am trying to get the duration and directions of a file that gives me the difference from 2 points. I got all the information right but now its just the passing it to the file but it give me bad output in my output file.
For example my read file is :
0,0,0
1,2,3
0,0,0
when i read it and do all the math it gives me the right answer that i am looking for in my getmoveinfo function but when i call the parameter of that function in my writemoveinfo it gets me a different answer which is:
-863204160.0000
-431602080.0000,-431602080.0000,-431602080.0000,-431602080.0000
this is my main:
typedef struct Vector Vector;
struct Vector
{
float x;
float y;
float z;
};
typedef struct MoveInfo MoveInfo;
struct MoveInfo
{
Vector direction;
float duration;
};
int main(int argc, char** argv)
{
// add your main function code here
char currentLine[MAX_LENGTH];
int numLines = 0;
FILE* inputFileName = fopen("points.txt", "r");
if (inputFileName == NULL)
{
printf("file open failed\n");
return (EXIT_FAILURE);
}
while (!feof(inputFileName))
{
fgets(currentLine, MAX_LENGTH, inputFileName);
numLines++;
}
Vector* points = malloc(numLines * sizeof(Vector));
for (int i = 0; i < numLines; i++)
{
fgets(currentLine, MAX_LENGTH, inputFileName);
getPointFromString(currentLine, &points[i]);
}
fclose(inputFileName);
//read in moveinfo data
MoveInfo* moveinfo = malloc((numLines-1) * sizeof(MoveInfo));
/*for (int i = 0; i < numLines; i++)
{
printf("point %d\n", i + 1);
printf("%f\n", points[i].x);
printf("%f\n", points[i].y);
printf("%f\n", points[i].z);
}
*/
int i = 0;
getMoveInfoBetweenPoints(&moveinfo[i], points[i], points[i + 1]);
FILE* outputfile = fopen("moveinfo.txt", "w");
if (outputfile == NULL)
{
printf("file open failed\n");
return (EXIT_FAILURE);
}
for (int i = 0; i < numLines; i++)
{
writeMoveInfoToFile(&moveinfo[i], outputfile);
}
fclose(outputfile);
return(EXIT_SUCCESS);
}
these are my functions:
int countInputFileLines(char inputFileName[]
{
int count = 0;
inputFileName = fopen("points.txt", "r");
int ch;
while (EOF != (ch = getc(inputFileName)))
{
if ('\n' == ch)
{
count++;
}
}
fclose(inputFileName);
return 0;
}
void getPointFromString(char string[], Vector* point)
{
int commaindex = -1;
char *result = NULL;
result = strchr(string, ',');
char *stringstart = &string[0];
commaindex = result - stringstart;
char* numberstring = malloc((commaindex + 1) * sizeof(char));
strncpy(numberstring, string, commaindex);
numberstring[commaindex] = '\0';
point->x = atof(numberstring);
string = &string[0] + commaindex + 1;
result = strchr(string, ',');
stringstart = &string[0];
commaindex = result - stringstart;
char* Ystring = malloc((commaindex + 2) * sizeof(char));
strncpy(Ystring, string, commaindex);
Ystring[commaindex] = '\0';
point->y = atof(Ystring);
/*point->z = string[commaindex + 1];
char* Zstring = malloc((commaindex + 1) * sizeof(char));
strncpy(Zstring, string, commaindex);
Zstring[commaindex] = '\0';
point->z = atoi(Zstring);
*/
string = &string[0] + commaindex + 1;
point->z = atof(string);
free(numberstring);
numberstring = NULL;
free(Ystring);
Ystring = NULL;
/*free(Zstring);
Zstring = NULL;
*/
}
void getMoveInfoBetweenPoints(MoveInfo* moveInfo, Vector firstPoint, Vector secondPoint)
{
float deltax = secondPoint.x - firstPoint.x;
float deltay = secondPoint.y - firstPoint.y;
float deltaz = secondPoint.z - firstPoint.z;
Vector direction;
direction.x = deltax;
direction.y = deltay;
direction.z = deltaz;
float duration= sqrtf(powf(direction.x, 2) + powf(direction.y, 2) + powf(direction.z, 2));
direction.x /= duration;
direction.y /= duration;
direction.z /= duration;
//printf("%.4f\n", duration * 2);
//printf("(%.4f %.4f %.4f %.4f )\n ", direction.x, direction.y, direction.z, duration );
}
void writeMoveInfoToFile(MoveInfo moveInfo[], int count)
{
int i = 0;
FILE* outputfile;
fprintf(outputfile, "%.4f", moveInfo[i].duration * 2);
fprintf(outputfile, "%.4f %.4f %.4f %.4f\n", moveInfo[i].direction.x, moveInfo[i].direction.y, moveInfo[i].direction.z, moveInfo[i].duration);
You are passing the file pointer outputfile to the function writeMoveInfoToFile(), but the function is not getting the file pointer correctly (the argument type if int instead of FILE* and instead of that a new uninitialized variable outputfile is used in the function.
Corrected function:
void writeMoveInfoToFile(MoveInfo moveInfo[], FILE* count) /* use correct type */
{
int i = 0;
FILE* outputfile = count; /* initialize this variable */
fprintf(outputfile, "%.4f", moveInfo[i].duration * 2);
fprintf(outputfile, "%.4f %.4f %.4f %.4f\n", moveInfo[i].direction.x, moveInfo[i].direction.y, moveInfo[i].direction.z, moveInfo[i].duration);
Also note that
MoveInfo* moveinfo = malloc(numLines-1 * sizeof(MoveInfo));
may not do what you want that to do. The * operator has higher precedence than - operator, so it will subtract sizeof(MoveInfO) from numLines.
If you want to allocate numLines-1 elements of MoveInfo, it should be:
MoveInfo* moveinfo = malloc((numLines-1) * sizeof(MoveInfo));
I'm trying to make an array of structs in c, but I can't make it work. When I try to run it, the program crashes.
typedef struct{
char name[20];
char manufacturer[20];
unsigned int price;
} product;
unsigned int stringToNr(char *numbers){
unsigned int nr = 0;
unsigned int i;
for (i = 0; i < strlen(numbers); i ++)
{
nr *= 10; nr += numbers[i] - '0';
}
return nr;
}
I have a function that would print the list to a file, sometimes it reaches this function, sometimes it crashes before.
void printList(product *products, unsigned int nr){
unsigned int i;
FILE *f;
f = fopen("output.txt", "w");
for (i = 0; i < nr; i ++){
fprintf(f, "%s ", products[i].name);
fprintf(f, "%s ", products[i].manufacturer);
fprintf(f, "%d\n", products[i].price);
}
fclose(f);
}
I have to use a separate function to read the list from file.
void readList(product **products, unsigned int *nr){
FILE *f;
f = fopen("input.txt", "r");
char *row;
row = malloc(sizeof(char) * 45);
unsigned int rowLength;
fgets(row, 45, f);
rowLength = strlen(row);
if (row[rowLength - 1] == '\n'){
rowLength--;
row[rowLength ] = '\0';
}
*nr = stringToNr(row);
products = malloc((*nr) * sizeof(product*));
unsigned int i;
char *rowElement;
for (i = 0; i < *nr; i ++){
fgets(row, 45, f);
rowElement = strtok(row, " ");
strcpy((*products)[i].name, rowElement);
rowElement = strtok(NULL, " ");
strcpy((*products)[i].manufacturer, rowElement);
rowElement = strtok(NULL, " ");
rowLength = strlen(row);
if (row[rowLength- 1] == '\n'){
rowLength--;
row[rowLength] = '\0';
}
(*products)[i].price = stringToNr(rowElement);
}
free(row);
fclose(f);
}
Obviously the program has more features, but those work fine.
int main(){
product *products;
unsigned int nr;
readList(&products, &nr);
printList(products, nr);
free(products);
return 0;
}
My input file looks like this:
3
AAA FactoryA 300
BBB FactoryC 550
ZZZ Factory5 100
Code ignores value of products.
What ever readList() receives in products is overwritten with the malloc() call.
void readList(product **products, unsigned int *nr){
...
// bad
products = malloc((*nr) * sizeof(product*));
Instead, use *products. Also allocate by the size of the referenced variable, not by the size of the type. Easier to code, review and maintain.
*products = malloc(sizeof *(*products) * (*nr));
if (*products == NULL) Handle_OOM();
Minor: After fgets(row, ..., ...); , following is not safe from a hacker exploit of reading an initial null character.
rowLength = strlen(row);
// What happens when rowLength == 0
if (row[rowLength- 1] == '\n'){
...
Instead code could use below to rid the optional trailing '\n'.
row[strcspn(row, "\n")] = '\0';
I have a program that uses word search. I have a data file which contains the puzzle and the words. What can i implement into my program so that it reads the file and stores the letters present in it as an array?
Example of the data file (it is called testdata):
h e l l o a c d
f g b w o r l d
h a c c v b n a
e q b x n t q q
y e h n c a q r
hello
world
hey
I want to store all the letters in a 2-d array.
Also, I need to store all the words in a 1-dimensional array.
The maximum number of rows of columns or rows that AxA square of letters that is possible in a data file is 25. So, I believe that I should declare an array of that size for the letter and then write them into that array.
I just can't figure out how to read them into that array. There is a space after each letter in the array and no spaces in the words so I think that might be helpful when putting the letters in one array and words in another.
Given your question, and your input, there are a few questions, but in the interest of time, for now, I have made some assumptions about the dimensions of the array, i.e. that it is not necessarily square (as implied by columns or rows that AxA square). The actual data sample disagrees, so I wrote a routine that counts everything as it goes. The letter array is simply an array of arrays, but since it is stored in sequential memory, it just looks like one long array. The strings are each in there own location as well. In any case, this code should illustrate enough to get you on the right track...
#include <ansi_c.h>
#include <stdio.h>
void GetFileContents(char *file, int *nWords, int *lw, int *r, int *c);
void allocMemoryStr(int numStrings, int max);
void allocMemoryLtr(int numStrings, int max);
void freeMemoryStr(int numStrings);
void freeMemoryLtr(int numletters);
#define FILENAME "c:\\dev\\play\\_puzzle.txt"
char **letters;
char **strings;
int main()
{
int longest, cnt, wCount, rows, cols, i;
char line[260];
FILE *fp;
char *buf=0;
GetFileContents(FILENAME, &wCount, &longest, &rows, &cols);
allocMemoryStr(wCount, longest); //for strings
allocMemoryLtr(rows*cols, 1); //for strings
//read file into string arrays
fp = fopen(FILENAME, "r");
cnt=0;
for(i=0;i<rows;i++)
{
fgets(line, 260, fp);
buf = strtok(line, " \n");
while(buf)
{
strcpy(letters[cnt], buf);
buf = strtok(NULL, " \n");
cnt++; //use as accurate count of words.
}
}
cnt=0;
while(fgets(line, 260, fp)) //get remainder of lines into strings
{
//[EDIT]removed fgets()
buf = strtok(line, " \n");
while(buf)
{
strcpy(strings[cnt], buf);
buf = strtok(NULL, " \n");
cnt++; //use as accurate count of words.
}
}
fclose(fp);
freeMemoryStr(wCount);
freeMemoryLtr(rows*cols);
return 0;
}
void GetFileContents(char *file, int *nWords, int *lw, int *r, int *c)
{
char line[260];
FILE *fp;
char *buf=0;
char temp[80];
int wc=0, rc=0, cc=0, ck=0;
fp = fopen(FILENAME, "r");
while(fgets(line, 260, fp))
{
rc++;
buf = strtok(line, " \n");
while(buf)
{
strcpy(temp, buf); // word handler
if(strlen(temp) > 1)
{
wc++;
rc--; //
}
else if(strlen(temp) == 1) //leter handler
{
cc++;
(cc>ck)?(ck=cc):(cc=cc);
}
buf = strtok(NULL, " \n");
}
cc = 0;
}
fclose(fp);
*nWords = wc;
*r = rc;
*c = ck;
}
void allocMemoryStr(int numStrings, int max)
{
int i;
strings = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
strings[i] = calloc(sizeof(char)*max + 1, sizeof(char));
}
}
void allocMemoryLtr(int numletters, int max)
{
int i;
letters = calloc(sizeof(char*)*(numletters+1), sizeof(char*));
for(i=0;i<numletters; i++)
{
letters[i] = calloc(sizeof(char)*max + 1, sizeof(char));
}
}
void freeMemoryStr(int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(strings[i]) free(strings[i]);
free(strings);
}
void freeMemoryLtr(int numletters)
{
int i;
for(i=0;i<numletters; i++)
if(letters[i]) free(letters[i]);
free(letters);
}
I would parse the file line by line and char by char looking for what i need. In the example (which is untested), i hold three counters to help filling the arrays correctly.
char letters[25][25];
char words[10][25]
int letters_x_pos = 0; // Row counter
int letters_y_pos = 0; // Column counter
int words_pos = 0;
for (int i = 0; i < 25; i++) {
for (int j = 0; j < 25; j++) {
letters[i][j] = '\0';
}
}
const char *line;
while (line = some_read_function()) {
if (!(strlen(line) > 1)) {
continue;
}
if (line[1] == ' ') {
// Line contains letters
const char *letter = line;
while (*letter != '\0') {
if (*letter == ' ' || *letter == '\n' || *letter == '\r') {
continue;
}
else {
letters[letters_x_pos][letters_y_pos++] = *letter;
}
if (letters_y_pos == 25) {
// Maximum reached
break;
}
letter++;
}
// Increment row counter and reset column counter
letters_x_pos++;
letters_y_pos = 0;
if (letters_x_pos == 25) {
// Maximum reached
break;
}
}
else {
// Line contains word
strncpy(words[words_pos++], line, 25);
if (words_pos == 25) {
// Maximum reached
break;
}
}
}