Structure Array not printing correctly | C++ - arrays

This is the structure
struct Student{
char firstName[MAX_LEN + 1];
char lastName[MAX_LEN + 1];
float gpa;
};
So let me say that StudentList1 has the correct data.
count Struct1 is how many names are entered.
Student StudentList1[10];
int count5 = 0, countfName = 0, countlName = 0;
while(count5 < countStruct1)
{
while(StudentList1[count5].firstName[countfName] != '\0')
{
StudentList2[count5].firstName[countfName] =
StudentList1[count5].firstName[countfName];
countfName++;
}
while(StudentList1[count5].lastName[countlName] != '\0')
{
StudentList2[count5].lastName[countlName] =
StudentList1[count5].lastName[countlName];
countlName++;
}
StudentList2[count5].gpa = StudentList1[count5].gpa;
count5++;
}
Now for some reason when I try this code, not using the arrays for characters of the last name and first name
while(count6 < count5)
{
cout << "Name: " << StudentList2[count6].firstName << " " << StudentList2[count6].lastName << "\n";
count6++;
}
Now when I try this doing it like this I just get a bunch of garbage, I get the first name printed but after that a whole bunch of garbage and the last name too but just garbage in between.

You're forgetting the terminating zero when you copy.
Since structs are copyable, you can do it like this:
while (count5 < countStruct1)
{
StudentList2[count5] = StudentList1[count5];
count5++;
}
or
for (int i = 0; i < countStruct1; i++)
{
StudentList2[i] = StudentList1[i];
}
which are slightly less error-prone.

In your code:
while(StudentList1[count5].firstName[countfName] != '\0')
{
StudentList2[count5].firstName[countfName] =
StudentList1[count5].firstName[countfName];
countfName++;
}
You have it stop when it hits the '\0', but you never re-write that '\0' to the end of the StudentList2

First, you need to copy the terminating zero:
StudentList2[count5].firstName[countfName] = '\0';
StudentList2[count5].lastName[countlName] = '\0';
then you need to reset your counters:
countfName = countlName = 0;
you should do this before the count5++ in your outermost while loop

Related

Count the occurrences of every word in C

I want to count the occurrences of every word of this small text " A broken heart of a broken mind ."
Every word of this text is in 2d array[100][20] in which 100 is the max_words and 20 is the max_word_length. And I have a pointers array[100] in which every pointer points the word. I can't find a clever way to count the same words,
for example
a: 2 times
broken: 2 times
heart: 1 time
mind: 1 time
. : 1 time
These would be the pointers and the words array:
POINTERS ARRAY WORDS ARRAY
point0(points "a") a
point1(points "broken") broken
point2(points "heart") heart
point3(points "of") of
point4 (points "a") mind
point5(points "broken") .
point6(points "mind") \0\0\0\0\0
point7(points ".") \0\0\0\0\0
NULL ..
NULL
..
NULL \0\0\0\0\0
Side note: Every word is lowercase.
void frequence_word(char *pointers[], int frequence_array[]) {
int word = 0;
int i;
int count = 1;
int check[MAX_WORDS];
for (word = 0; word < MAX_WORDS; word++) {
check[word] = -1;
}
for (word = 0; word < MAX_WORDS; word++) {
count = 1;
for (i = word + 1; i < MAX_WORDS; i++) {
if (pointers[word + 1] != NULL
&& strcmp(pointers[word], pointers[i]) == 0) {
count++;
check[i] = 0;
}
}
if (check[word] != 0) {
check[word] = count;
}
}
}
Any ideas please?
This seems like a use case for strstr. You can call strstr, then iteratively reassign to the original string until NULL is reached.
const char substring[] = "A broken heart of a broken mind";
const char* total = ...;
const char* result;
long count = 0;
while (result = strstr(total, substring)) {
count++;
total += (sizeof(substring) - 1);
}
I think this is mostly self-explanetory, but I will explain this line:
total += (sizeof(substring) - 1);
It takes advantage of the fact that sizeof on arrays returns the array length. Thus, sizeof on a character array returns the number of characters in it. We subtract one to ignore the null terminator.

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;
}

code accounting for multiple delimiters isn't working

I have a program I wrote to take a string of words and, based on the delimiter that appears, separate each word and add it to an array.
I've adjusted it to account for either a ' ' , '.' or '.'. Now the goal is to adjust for multiple delimiters appearing together (as in "the dog,,,was walking") and still only add the word. While my program works, and it doesn't print out extra delimiters, every time it encounters additional delimiters, it includes a space in the output instead of ignoring them.
int main(int argc, const char * argv[]) {
char *givenString = "USA,Canada,Mexico,Bermuda,Grenada,Belize";
int stringCharCount;
//get length of string to allocate enough memory for array
for (int i = 0; i < 1000; i++) {
if (givenString[i] == '\0') {
break;
}
else {
stringCharCount++;
}
}
// counting # of commas in the original string
int commaCount = 1;
for (int i = 0; i < stringCharCount; i++) {
if (givenString[i] == ',' || givenString[i] == '.' || givenString[i] == ' ') {
commaCount++;
}
}
//declare blank Array that is the length of commas (which is the number of elements in the original string)
//char *finalArray[commaCount];
int z = 0;
char *finalArray[commaCount] ;
char *wordFiller = malloc(stringCharCount);
int j = 0;
char current = ' ';
for (int i = 0; i <= stringCharCount; i++) {
if (((givenString[i] == ',' || givenString[i] == '\0' || givenString[i] == ',' || givenString[i] == ' ') && (current != (' ' | '.' | ',')))) {
finalArray[z] = wordFiller;
wordFiller = malloc(stringCharCount);
j=0;
z++;
current = givenString[i];
}
else {
wordFiller[j++] = givenString[i];
}
}
for (int i = 0; i < commaCount; i++) {
printf("%s\n", finalArray[i]);
}
return 0;
}
This program took me hours and hours to get together (with help from more experienced developers) and I can't help but get frustrated. I'm using the debugger to my best ability but definitely need more experience with it.
/////////
I went back to pad and paper and kind of rewrote my code. Now I'm trying to store delimiters in an array and compare the elements of that array to the current string value. If they are equal, then we have come across a new word and we add it to the final string array. I'm struggling to figure out the placement and content of the "for" loop that I would use for this.
char * original = "USA,Canada,Mexico,Bermuda,Grenada,Belize";
//creating two intialized variables to count the number of characters and elements to add to the array (so we can allocate enough mmemory)
int stringCharCount = 0;
//by setting elementCount to 1, we can account for the last word that comes after the last comma
int elementCount = 1;
//calculate value of stringCharCount and elementCount to allocate enough memory for temporary word storage and for final array
for (int i = 0; i < 1000; i++) {
if (original[i] == '\0') {
break;
}
else {
stringCharCount++;
if (original[i] == ',') {
elementCount++;
}
}
}
//account for the final element
elementCount = elementCount;
char *tempWord = malloc(stringCharCount);
char *finalArray[elementCount];
int a = 0;
int b = 0;
//int c = 0;
//char *delimiters[4] = {".", ",", " ", "\0"};
for (int i = 0; i <= stringCharCount; i++) {
if (original[i] == ',' || original[i] == '\0') {
finalArray[a] = tempWord;
tempWord = malloc(stringCharCount);
tempWord[b] = '\0';
b = 0;
a++;
}
else {
tempWord[b++] = original[i];
}
}
for (int i = 0; i < elementCount; i++) {
printf("%s\n", finalArray[i]);
}
return 0;
}
Many issues. Suggest dividing code into small pieces and debug those first.
--
Un-initialize data.
// int stringCharCount;
int stringCharCount = 0;
...
stringCharCount++;
Or
int stringCharCount = strlen(givenString);
Other problems too: finalArray[] is never assigned a terminarting null character yet printf("%s\n", finalArray[i]); used.
Unclear use of char *
char *wordFiller = malloc(stringCharCount);
wordFiller = malloc(stringCharCount);
There are more bugs than lines in your code.
I'd suggest you start with something much simpler.
Work through a basic programming book with excercises.
Edit
Or, if this is about learning to program, try another, simpler programming language:
In C# your task looks rather simple:
string givenString = "USA,Canada Mexico,Bermuda.Grenada,Belize";
string [] words = string.Split(new char[] {' ', ',', '.'});
foreach(word in words)
Console.WriteLine(word);
As you see, there are much issues to worry about:
No memory management (alloc/free) this is handeled by the Garbage Collector
no pointers, so nothing can go wrong with them
powerful builtin string capabilities like Split()
foreach makes loops much simpler

Grouping characters to form strings in c

I am doing a school C project. In the project , I have 48 characters hold in char holdReference[48] and every 8 of them must form 1 string. Thus, for example:
holdReference[0] = '0';
holdReference[1] = '0';
holdReference[2] = '0';
holdReference[3] = '0';
holdReference[4] = '1';
holdReference[5] = '2';
holdReference[6] = 'd';
holdReference[7] = '8';
....
Result strings formed by 8 characters hold in char HexReference[6][9] which means that HexReference holds 6 strings which have 8-bit length.
Here is my code:
char HexReference[6][9];
int hx = 0;
int indexxx;
int hex = -1;
while(hx<charNumber)
{
if(hx%8 == 0)
{
indexxx = 0;
hex++;
HexReference[hex][indexxx] = holdReference[hx];
indexxx++;
}
else
{
HexReference[hex][indexxx] = holdReference[hx];
indexxx++;
}
hx++;
}
printf("%s" , HexReference[0]); --> prints 000012d8/000017f3
Problem is that even if HexReference[0] must hold 000012d8 , 000012d8/000017f3 is printed on the console. 000017f3 must be hold in HexReference[1].
I will be very thankful if you help me soon.
You forgot to allocate enough space for the null-terminator "\0" at the end of each string.
And also since you are putting the chars one by one you also need to add the null-terminator manually.
the reason could be you did not added '\0' after first row data end so that is why second row string is printed with that
This should work
char HexReference[6][10];
int hx = 0;
int indexxx;
int hex = -1;
while(hx<charNumber)
{
if(hx%8 == 0)
{
indexxx = 0;
hex++;
HexReference[hex][indexxx] = holdReference[hx];
HexReference[hex][10] =0;
indexxx++;
}
else
{
HexReference[hex][indexxx] = holdReference[hx];
indexxx++;
}
hx++;
}
printf("%s" , HexReference[0]);

User-defined function similar to squeeze()

So I'm trying to do the practice exercises in K&R. It wants me to make a function similar to squeeze, I don't get whats wrong with it. I desk checked it already. I don't want a solution found on the net, I wanna understand why my code wont work.
//removes characters that are present in both strings
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define MAXLTR 15
void removesame(char s1[],char s2[]);
int main(void)
{
char string1[MAXLTR],string2[MAXLTR];
printf("Enter a string: ");
scanf("\n%s",&string1);
printf("\nEnter the letters/words to be removed: ");
scanf("\n%s",&string2);
removesame(string1,string2);
printf("\nFinal output: %s",string1);
getch();
}
void removesame(char s1[],char s2[])
{
char temp[MAXLTR];
int arraycntr,comparecntr;
for(comparecntr = 0; comparecntr < MAXLTR; comparecntr++)
{
for(arraycntr = 0;arraycntr < MAXLTR;arraycntr++)
{
if(s1[arraycntr] == s2[arraycntr])
s1[arraycntr] == '\t';
}
}
comparecntr = 0;
for(arraycntr = 0; arraycntr < MAXLTR; arraycntr++)
{
if(s1[arraycntr] != '\t')
{
temp[comparecntr] = s1[arraycntr];
++comparecntr;
}
}
for(arraycntr = 0; arraycntr < MAXLTR; arraycntr++)
s1[arraycntr] = '\0';
for(arraycntr = 0;arraycntr < MAXLTR; arraycntr++)
s1[arraycntr] = temp[arraycntr];
}
This is not an assignment, but is an equality test:
s1[arraycntr] == '\t';
you meant:
s1[arraycntr] = '\t';
If you compile with a high warning level, the compiler may emit a message alerting you to this. The Microsoft VC compiler emits the following warning:
C:\devel\cpp\stackoverflow\main.c(32) : warning C4553: '==' : operator has no effect; did you intend '='?
The initial for loops only check if s1 and s2 have the same values in the same indexes, it does not check if a char in s1 exists anywhere in s2. The terminating conditions on the for loops should also be the lengths of s1 and s2, not MAXLTR:
size_t arraycntr,comparecntr;
for(comparecntr = 0; comparecntr < strlen(s2); comparecntr++)
{
for(arraycntr = 0;arraycntr < strlen(s1) ;arraycntr++)
{
if(s1[arraycntr] == s2[comparecntr])
s1[arraycntr] = `\t`;
}
}
The next for loop should use strlen(s1) also and just assign null terminator to temp after:
comparecntr = 0;
for(arraycntr = 0; arraycntr < strlen(s1); arraycntr++)
{
if(s1[arraycntr] != `\t`)
{
temp[comparecntr] = s1[arraycntr];
++comparecntr;
}
}
temp[comparecntr] = '\0';
temp is not initialised anywhere, so contains random data, apart from that just entered during this for. Without a null terminator in temp, s1 will end with no null terminator also (you will probably see garbage printed afterwards). Finally, just strlen(temp) + 1 when populating s1:
for(arraycntr = 0;arraycntr < strlen(temp) + 1; arraycntr++)
s1[arraycntr] = temp[arraycntr];
The + 1 will copy the null terminator to s1.
Minor note, instead of calling strlen() in the terminating condition of the for loops you can store this instead:
size_t chars_to_copy;
for(arraycntr = 0, chars_to_copy = strlen(temp) + 1;
arraycntr < chars_to_copy;
arraycntr++)
{
s1[arraycntr] = temp[arraycntr];
}

Resources