random numbers being read into array instead of the text file values - arrays

I am trying to make a function that reads all the numbers from a text file into an array, where each line of the file has a number, ex:
57346
40963
24580
98307
98312
32777
10
16392
16396
...
My function does allocate the necessary size to store the values, but the values being stored are random ones and 0's that aren't in my text file. Output ex:
0
0
296386
0
-485579776
-653048057
584
0
2095946880
...
This is my code:
typedef struct set{
void** values;
int size;
}Set;
int checkSize(FILE* file) {
int counter = 0;
char chr;
chr = getc(file);
while (chr != EOF) {
if (chr == '\n') {
counter = counter + 1;
}
chr = getc(file);
}
return counter;
}
Set* readSet(FILE* file){
Set* new = malloc(sizeof(Set));
new->size = checkSize(file);
new->values = malloc(sizeof(void*)*new->size);
int arrayAux[new->size];
int i = 0, n;
while(i < new->size) {
fscanf(file, "%ld", &arrayAux[i]);
new->values[i] = arrayAux[i];
i++;
}
//loop to remove the first three lines of the file, which are the number of values in the file,
//the biggest value of the file and the division between the number of values and the biggest value
for(i = 0; i < 3; i++) {
new->values[i] = new->values[i + 1];
new->size--;
}
for (i = 0; i <= new->size; i++) {
printf("%d\n", new->values[i]);
}
return new;
}
How can I fix this? Thanks in advance for any help.

Why void and not long?
You cannot do int arrayAux[new->size]; as size is a variable and thus cannot be used at compile time !!! 100% guarantee of reading out of bounds.
Read the value from file into a long and assign it to the proper space in your list.
Why have the size in every row? Use a global int
why loop to step over the first three in the list?
size -=3
i+=3
Works just as well

Related

Segmentation Fault when My Code Executes the printf() in c

below I have posted my code. When I compile I receive no errors, and only one warning about variables I haven't used yet. the code works all the way to the line in code where it starts to print. I have tested all the sections and I believe that one is at fault. please let me know what I am doing wrong so I can fix it.
#include <stdio.h>
#include <string.h>
#define NUM_LINES 37
#define LINE_LENGTH 60
void select_sort_str(char list[NUM_LINES][LINE_LENGTH], int n);
int alpha_first(char list[NUM_LINES][LINE_LENGTH], int min_sub, int max_sub);
int main (void){
//store each line in an array of strings
FILE *inp;
FILE *outp;
char hurr[NUM_LINES][LINE_LENGTH];
;
inp = fopen("hurricanes.csv","r");
outp = fopen("out.txt","w");
//read in lines from file
for (int i = 0; i<NUM_LINES; i++){
fgets(hurr[i], LINE_LENGTH, inp);
}
inp = fopen("hurricanes.cvs","r");
//printf("%s", hurr[0]);
//define function
select_sort_str(hurr, NUM_LINES);
return(0);
}
int
alpha_first(char list[NUM_LINES][LINE_LENGTH], // input - array of pointers to strings
int min_sub, // input - min and max subscripts of
int max_sub) // portion of list to consider
{
int first, i;
first = min_sub;
for (i = min_sub + 1; i <= max_sub; ++i) {
if (strcmp(list[i], list[first]) < 0) {
first = i;
}
}
return (first);
}
/*
* Orders the pointers in an array list so they access strings in
* alphabetical order
* Pre: first n elements of list reference string of uniform case;
* n >= 0
*/
void
select_sort_str(char list[NUM_LINES][LINE_LENGTH], // input/output - array of pointers being
// ordered to acces strings alphabetically
int n) // input - number of elements to sort
{
int fill, // index of element to contain next string in order
index_of_min; // index of next string in order
char *temp;
char temp1[NUM_LINES][LINE_LENGTH];
for (fill = 0; fill < n - 1; ++fill) {
index_of_min = alpha_first(list, fill, n - 1);
if (index_of_min != fill) {
temp = list[index_of_min];
list[index_of_min][LINE_LENGTH] = list[fill][LINE_LENGTH];
strncpy(temp1[index_of_min], list[index_of_min], LINE_LENGTH);
temp1[fill][LINE_LENGTH] = *temp;
}
}
char *name;
char *cat = 0;
char *date;
for (int i = 0; i<NUM_LINES; i++){
name = strtok(NULL, ",");
cat = strtok(NULL, "h");
date = strtok(NULL, " ");
printf("%s %s %s\n", name, cat, date);
}
// for( int i =0; i<NUM_LINES; i++){
// printf("%s", list[i]);
// }
}
The only first parameter you ever pass to strtok is NULL. You never actually give it anything to parse. Did you perhaps mean strtok(temp1[i], ",");?
Also, why no error checking? It's much easier to find bugs in code with error checking.

How to check first letter of one string with last letter of another string inside of same char array

How can I complete the function canArrangeWords() ?
Question : Given a set of words check if we can arrange them in a list such that the last letter of any word and first letter of another word are same. The input function canArrangeWords shall contain an integer num and array of words arr. num denotes the number of word in the list (1<=num<=100). arr shall contain words consisting of lower case letters between 'a' - 'z' only . return 1 if words can be arranged in that fashion and -1 if cannot.
Input : 4 pot ten nice eye
output : 1
input : 3 fox owl pond
output: -1
Please help me complete this program .
**
#include<stdio.h>
#include<string.h>
int canArrangewords(int,char [100][100]);
void main(){
int n ,count=0 , i ;
char arrayS[100][100];
scanf("%d",&n);
for (i = 0; i < n; ++i)
{
scanf("%s",arrayS[i]);
}
for(i=0;i<n;i++)
{
printf("%s",arrayS[i]);
printf("\n");
}
printf("%c\n",arrayS[2][4]);
canArrangewords(n , arrayS);
}
int canArrangewords(int n,char arrayS[100][100]){
int i , j ;
for ( i = 0; i < n; i++)
{
for ( j = i+1 ; j < strlen(arrayS[j+1]); i++)
{
int flag = strlen(arrayS[j+1]) - 1;
int temp = strcmp(arrayS[i][0],arrayS[j][flag]);
}
}
}
}
Well, first of all think of the way you can reach that answer.
If you only need to know if they can or can not be arranged and you do not have to do so your self you can use an empty array of int array[26] for each letter a-z.
The rule is that from all the first and last letters for all the words only two MAY appear an odd amount of times - the first letter of first word in list and the last letter in the last word in the list, the rest MUST appear an even amount of times. I would add a check to make sure the letters are lowercase as well. good luck!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINASCII 97
#define LETTERS 26
void UpdateArray(char letter, int* arr)
{
if(arr[letter - MINASCII] == 0)
{
++arr[letter - MINASCII];
}
else
{
--arr[letter - MINASCII];/*for each second time same letter is seen reduce back to zero */
}
}
int canArrangewords(int wordNum, char* wordArr[])
{
int arr[LETTERS] = {0};
int i = 0;
int count = 0 ;
char first;
char last;
char* string;
for (i= 0; i< wordNum; ++i)
{
string = wordArr[i];
first = string[0];
last = string[strlen(string)-1];
UpdateArray(first, &arr[0]);
UpdateArray(last, &arr[0]);
}
for(i = 0; i< LETTERS; ++i)
{
count+=arr[i];
}
if(count == 2 || count == 0)/*either once each or twice -see word1 example in main*/
{
return 1;
}
return -1;
}
int main()
{
int i = 0;
char* words[] = {"pot", "ten", "nice", "eye"};
char* words1[] = {"pot", "ten", "nip"};
char* words2[] = {"fox", "owl", "pond"};
i = canArrangewords(4,words);
printf("%d\n", i);
i = canArrangewords(3,words1);
printf("%d\n", i);
i = canArrangewords(3,words2);
printf("%d\n", i);
return 0;
}
Change your array of words into an array of pointers to words. Then you can simply exchange the pointers.
To speed things up, instead of a pointer to a word, have it point to a structure:
struct WORD {
char *firstchar; // begin of word
char *lastchar; // last char of word
} *words[100]; // array of 100 pointers to words
To read the words:
char buf[100];
for (i = 0; i < n; ++i)
{
scanf("%s",buf);
int len= strlen(buf);
words[i]= malloc(sizeof(struct WORDS));
words[i]->firstchar= malloc(len+1);
strcpy(words[i]->firstchar, buf);
words[i]->lastchar= words[i]->firstchar + len-1;
}
Now compare and sort:
if (*words[i]->lastchar == *words[j]->firstchar) {
struct WORDS *tmp= words[i+1];
words[i+1]= words[j];
words[j]= tmp;
}
Do this in a loop, a kind of bubble sort. I leave that to you.

Count of similar characters without repetition, in two strings

I have written a C program to find out the number of similar characters between two strings. If a character is repeated again it shouldn't count it.
Like if you give an input of
everest
every
The output should be
3
Because the four letters "ever" are identical, but the repeated "e" does not increase the count.
For the input
apothecary
panther
the output should be 6, because of "apther", not counting the second "a".
My code seems like a bulk one for a short process. My code is
#include<stdio.h>
#include <stdlib.h>
int main()
{
char firstString[100], secondString[100], similarChar[100], uniqueChar[100] = {0};
fgets(firstString, 100, stdin);
fgets(secondString, 100, stdin);
int firstStringLength = strlen(firstString) - 1, secondStringLength = strlen(secondString) - 1, counter, counter1, count = 0, uniqueElem, uniqueCtr = 0;
for(counter = 0; counter < firstStringLength; counter++) {
for(counter1 = 0; counter1 < secondStringLength; counter1++) {
if(firstString[counter] == secondString[counter1]){
similarChar[count] = firstString[counter];
count++;
break;
}
}
}
for(counter = 0; counter < strlen(similarChar); counter++) {
uniqueElem = 0;
for(counter1 = 0; counter1 < counter; counter1++) {
if(similarChar[counter] == uniqueChar[counter1]) {
uniqueElem++;
}
}
if(uniqueElem == 0) {
uniqueChar[uniqueCtr++] = similarChar[counter];
}
}
if(strlen(uniqueChar) > 1) {
printf("%d\n", strlen(uniqueChar));
printf("%s", uniqueChar);
} else {
printf("%d",0);
}
}
Can someone please provide me some suggestions or code for shortening this function?
You should have 2 Arrays to keep a count of the number of occurrences of each aplhabet.
int arrayCount1[26],arrayCount2[26];
Loop through strings and store the occurrences.
Now for counting the similar number of characters use:
for( int i = 0 ; i < 26 ; i++ ){
similarCharacters = similarCharacters + min( arrayCount1[26], arrayCount2[26] )
}
There is a simple way to go. Take an array and map the ascii code as an index to that array. Say int arr[256]={0};
Now whatever character you see in string-1 mark 1 for that. arr[string[i]]=1; Marking what characters appeared in the first string.
Now again when looping through the characters of string-2 increase the value of arr[string2[i]]++ only if arr[i] is 1. Now we are tallying that yes this characters appeared here also.
Now check how many positions of the array contains 2. That is the answer.
int arr[256]={0};
for(counter = 0; counter < firstStringLength; counter++)
arr[firstString[counter]]=1;
for(counter = 0; counter < secondStringLength; counter++)
if(arr[secondString[counter]]==1)
arr[secondString[counter]]++;
int ans = 0;
for(int i = 0; i < 256; i++)
ans += (arr[i]==2);
Here is a simplified approach to achieve your goal. You should create an array to hold the characters that has been seen for the first time.
Then, you'll have to make two loops. The first is unconditional, while the second is conditional; That condition is dependent on a variable that you have to create, which checks weather the end of one of the strings has been reached.
Ofcourse, the checking for the end of the other string should be within the first unconditional loop. You can make use of the strchr() function to count the common characters without repetition:
#include <stdio.h>
#include <string.h>
int foo(const char *s1, const char *s2);
int main(void)
{
printf("count: %d\n", foo("everest", "every"));
printf("count: %d\n", foo("apothecary", "panther"));
printf("count: %d\n", foo("abacus", "abracadabra"));
return 0;
}
int foo(const char *s1, const char *s2)
{
int condition = 0;
int count = 0;
size_t n = 0;
char buf[256] = { 0 };
// part 1
while (s2[n])
{
if (strchr(s1, s2[n]) && !strchr(buf, s2[n]))
{
buf[count++] = s2[n];
}
if (!s1[n]) {
condition = 1;
}
n++;
}
// part 2
if (!condition ) {
while (s1[n]) {
if (strchr(s2, s1[n]) && !strchr(buf, s1[n]))
{
buf[count++] = s1[n];
}
n++;
}
}
return count;
}
NOTE: You should check for buffer overflow, and you should use a dynamic approach to reallocate memory accordingly, but this is a demo.

c string: put ' ' if a word found in the sentence

I made a code and my target is to put spacewhere the input word was found in a sentence.
i neet to replece the small word with space
like:
Three witches watched three watches
tch
output:
Three wi es wa ed three wa es
I made this code:
#include<stdio.h>
#define S 8
#define B 50
void main() {
char small[S] = {"ol"};
char big[B] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
for (i = 0; i < B; i++)
{
for(j=0;j<S;j++)
{
if(small[j]!=big[i])
{
j=0;
break;
}
if(small[j]=='\0')
{
while (i-(j-1)!=i)
{
i = i - j;
big[i] = '\n';
i++;
}
}
}
}
puts(big);
}
First of all, in your exemple you work with newline '\n' and not with space.
Consider this simple example:
#include<stdio.h>
#define S 8
#define B 50
void main() {
char small[S] = {"ol"};
char big[B] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
int cpt = 0;
int smallSize = 0;
// loop to retrieve smallSize
for (i = 0; i < S; i++)
{
if (small[i] != '\0')
smallSize++;
}
// main loop
for (i = 0; i < B; i++)
{
// stop if we hit the end of the string
if (big[i] == '\0')
break;
// increment the cpt and small index while the content of big and small are equal
if (big[i] == small[j])
{
cpt++;
j++;
}
// we didn't found the full small word
else
{
j = 0;
cpt = 0;
}
// test if we found the full word, if yes replace char in big by space
if (cpt == smallSize)
{
for (int k = 0; k < smallSize; k++)
{
big[i-k] = ' ';
}
j = 0;
cpt = 0;
}
}
puts(big);
}
You need first to retrieve the real size of the small array.
Once done, next step is to look inside "big" if there is the word small inside. If we find it, then replace all those char by spaces.
If you want to replace the whole small word with a single space, then you'll need to adapt this example !
I hope this help !
A possible way is to use to pointers to the string, one for reading and one for writing. This will allow to replace an arbitrary number of chars (the ones from small) with a single space. And you do not really want to nest loops but une only one to process every char from big.
Last but not least, void main() should never be used except in stand alone environment (kernel or embedded development). Code could become:
#include <stdio.h>
#define S 8
#define B 50
int main() { // void main is deprecated...
char small[S] = {"ol"};
char big[B] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
int k = 0; // pointer to written back big
for (i = 0; i < B; i++)
{
if (big[i] == 0) break; // do not process beyond end of string
if(small[j]!=big[i])
{
for(int l=0; l<j; l++) big[k++] = small[l]; // copy an eventual partial small
big[k++] = big[i]; // copy the incoming character
j=0; // reset pointer to small
continue;
}
else if(small[++j] == 0) // reached end of small
{
big[k++] = ' '; // replace chars from small with a single space
j = 0; // reset pointer to small
}
}
big[k] = '\0';
puts(big);
return 0;
}
or even better (no need for fixed sizes of strings):
#include <stdio.h>
int main() { // void main is deprecated...
char small[] = {"ol"};
char big[] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
int k = 0; // pointer to written back big
for (i = 0; i < sizeof(big); i++)
{
if(small[j]!=big[i])
...
In C strings are terminated with a null character '\0'. Your code defines a somehow random number at the beginning (B and S) and iterates over that much characters instead of the exact number of characters, the strings actually contain. You can use the fact that the string is terminated by testing the content of the string in a while loop.
i = 0;
while (str[i]) {
...
i = i + 1;
}
If you prefer for loops you can write it also as a for loop.
for (i = 0; str[i]; i++) {
...
}
Your code does not move the contents of the remaining string to the left. If you replace two characters ol with one character , you have to move the remaining characters to the left by one character. Otherwise you would have a hole in the string.
#include <stdio.h>
int main() {
char small[] = "ol";
char big[] = "my older gradmom see my older sister";
int s; // index, which loops through the small string
int b; // index, which loops through the big string
int m; // index, which loops through the characters to be modified
// The following loops through the big string up to the terminating
// null character in the big string.
b = 0;
while (big[b]) {
// The following loops through the small string up to the
// terminating null character, if the character in the small
// string matches the corresponding character in the big string.
s = 0;
while (small[s] && big[b+s] == small[s]) {
// In case of a match, continue with the next character in the
// small string.
s = s + 1;
}
// If we are at the end of the small string, we found in the
// big string.
if (small[s] == '\0') {
// Now we have to modify the big string. The modification
// starts at the current position in the big string.
m = b;
// First we have to put the space at the current position in the
// big string.
big[m] = ' ';
// And next the rest of the big string has to be moved left. The
// rest of the big string starts, where the match has ended.
while (big[b+s]) {
m = m + 1;
big[m] = big[b+s];
s = s + 1;
}
// Finally the big string has to be terminated by a null
// character.
big[m+1] = '\0';
}
// Continue at next character in big string.
b = b + 1;
}
puts(big);
return 0;
}

How to store a number string in a file as a seperate integer in an array in C

I have 32 bits as a text file in Sender.txt like
00100100101110001111111100000001
I want to store each individual number as an integer in the array. I have tried the following code but not working.
#include <stdio.h>
#include<stdlib.h>
void main()
{
FILE *myfile;
myfile = fopen("Sender.txt" , "r");
char data[32];
int i,con, data1[32];
for(i=0;i<32;i++)
{
fscanf(myfile, "%1s", &data[i]);
}
for(i=0;i<32;i++)
{
con = atoi(data[i]);
data1[i]=con;
}
for(i=0;i<32;i++)
{
printf("%d \n", &data1[i]);
}
}
Still without fully understanding the purpose of your endeavor, I suggest to rewrite the first two loops:
for(i = 0; i < 32; i++)
{
int next = fgetc(myfile);
data1[i] = (next == '0') : 0 ? 1;
}
This code assumes that the file has 32 1's or 0's, all on the same line, and nothing else.
This could be further compressed, possibly at the expense of clarity:
for(i = 0; i < 32; i++)
{
data1[i] = fgetc(myfile) - '0';
}
Why don't you use fgetc ? This function reads only one Charakter and returns it.
Your code should then look like this:This one got errors see EDIT
FILE *file;
char c[32];
for(int i = 0; i < 32; i++){
if((c[i] = fgetc(file)) == NULL)
//then Error
}
fclose(file);
EDIT: As rightly pointed out by "alk" (what a name mate xD) The if clause makes no sense at all. It was to early in the morning i apologize. The right code should of course look like this:
FILE *file;
int data[32]; //The Question was to store the Data in an int not char like i did...
for(int i = 0; i < 32; i++)
data[i] = fgetc(file) - '0';
fclose(file);
Best regards

Resources