Remove empty strings of array of string in C - arrays

I made a program that reads the output from a text file line by line and puts it into an array. So I got an array of strings.
The problem arises when I go through that array of strings and check if those strings meet certain conditions. When I form an array of strings that meet a certain condition, I get empty lines as array elements.
For Example:
Expressions in a text file:
X&Y
X|Y
!X
(X|Y)|Z
(X&Y)|Z
(X&Y)&Z
(X&Y)|Z&(A|B
((X|Y)|Z)&((A|B)|(C&D))
(X&Y)|(Z&(A|B))
(A|B)&(!C)
A|(B&(C&(D|E)))
((X|Y)|(Z&(A|B)))|((C&D)&(D|E))
(A|B)|(C&D)&(D|E)
!A&(B|C)
(A|B)|(C|D)&(D
!A|(B&C)
When I print a new array of strings whose elements meet a certain condition, I get empty lines as elements.
X&Y
X|Y
!X
(X|Y)|Z
(X&Y)|Z
(X&Y)&Z
//Here
((X|Y)|Z)&((A|B)|(C&D))
(X&Y)|(Z&(A|B))
(A|B)&(!C)
A|(B&(C&(D|E)))
((X|Y)|(Z&(A|B)))|((C&D)&(D|E))
(A|B)|(C&D)&(D|E)
!A&(B|C)
//Here
Some elements that should be printed are not printed because of those empty lines? Can someone help me remove these empty lines?
Here's code:
int main()
{
FILE *dat;
int number_of_elements;
char str[MAX][MAXLEN];
int NumberOfRightBracket=0;
int NumberOFLeftBracket=0;
int NumberOfOperators=0;
int Number=0;
int i=0;
char g[200][MAXLEN];
dat=fopen("dat.txt","r");
if(dat==NULL)
{
printf("Error");
}
while(!feof(dat) && !ferror(dat))
{
if(fgets(str[i],100,dat)!=NULL)
str[i][strcspn(str[i],"\n")] = 0;
char p[100];
strcpy(p,str[i]);
for(int o=0;o<strlen(p);o++)
{
if(p[o]=='(')
NumberOfLeftBracket++;
else if(p[o]==')')
NumberOfRightBracket++;
else if(p[o]=='*' || p[o]=='|' || p[o]=='&' || p[o]=='!')
NumberOfOperators++;
}
if(NumberOfRightBracket!=0 && NumberOfLeftBracket!=0 && NumberOfRightBracket==NumberOfLeftBracket)
{
strcpy(g[i],p);
Number++;
}
else if(NumberOfRightBracket==0 && NumberOfLeftBracket==0 && NumberOfOperators==1)
{
strcpy(g[i],p);
Number++;
}
NumberOfRightBracket=0;
NumberOfLeftBracket=0;
NumberOfOperators=0;
i++;
}
for(int k=0;k<Number;k++)
{
printf("%s\n",g[k];
}
}

You use i to decide where in g to store each line from the input, and i is incremented in every iteration, but you use Number to count the number of retained strings, and you only increment Number when retaining a string.
The result is various g[i] where you decided not to retain a string never get updated with data from a line, but you do print them.
You do not need both i and Number. Use just one variable to keep track of both how many lines you have so far and where to put the next line in g.
(You also do not need g if the program is only supposed to do what it appears to be currently attempting.)

Related

A string of codes connected to multiple strings.I have some doubts about the two dimensional array and the for loop. Thank you very much!

/* link many strings*/
#include<stdio.h>
char *mystrcat(char * strDest, char * strSrc);
int main(void)
{
int n;
while(scanf("%d",&n))//输入要连接的字符串个数
{
if(n==0) break;//输入0结束
else
{
char words[n][100];
int i=0;
int j;
for(i=0;i<=n;i++)
{
while(fgets(words[i],100,stdin)!=NULL)
{
j=0;
while(words[i][j]!='\n')
j++;
if(words[i][j]=='\n') words[i][j]='\0';break;
}
}//输入字符串
for(i=n;i>0;i--)
{
mystrcat(words[i-1],words[i]);
}//连接这几个字符串
fputs(words[0],stdout);//输出字符串
printf("\n");
}
}
return 0;
}
//strcat函数原型
char *mystrcat(char * strDest,char * strSrc)
{
char *res=strDest;
while(*strDest)strDest++;
while(*strDest=*strSrc)
{
strDest++;
strSrc++;
}
return res;
}
This is a string of correct code to connect multiple strings. But I think n should be n-1 in two for cycles. But if you change the n to n-1, you can only enter n-1 strings, one less than I think. Can you tell me where my idea is wrong?
for(i=0;i<=n;i++)
Accessing array index out of bound when i=n - this is undefined behavior. So of course indexing should be from n-1 to 0( at max) or 0 to n-1.
And also array indexing in C starts from 0. So there are n elements that you are accessing, not n-1.
So corrections would be
for(i=0;i<=n-1;i++)
The thing is - you are reading in the n locations having index 0 to n-1 on the array and then you concatenate them one by one and at last all concatenated strings will be in words[0]. You are printing it out.
The second loop would be like
for(i=n-1;i>0;i--)
{
mystrcat(words[i-1],words[i]);
}
The idea is no matter what while accessing array indices don't access array index out bound. Here you can simply write it like this as shown in the second case. The thing is here we have ensured that all the indices used are from {0,1,2,3...,n-1}.
First determine what you want to do, if you want to take n string and then try to concatenate them then yes you can. That's what is being done here. but a much cleaner way to do it would be that keep a different result string on which you will concatenate n strings. That will not overwrite or change the already inputted strings.

How do i change the format of I/O?

Input format: The first line of input gives the number the input strings (without spaces and of maximum 100 length
and in lowercase). Then there is following n lines, each containing a string.
Output format: N lines of output, each line has either YES or NO following by newline. (YES if string is a magic square palindrome otherwise NO)
Sample Input:
4
satorarepotenetoperarotas
aba
abba
abcabacba
Sample Output:
YES
NO
YES
NO
So i have written the following code.But in my program the output gets displayed immediately after the input and it takes only one input at a time.
PS:If you have any suggestions on how to make the code more efficient,please add them in your answer.Thanks
#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{ int num_input,l;
scanf("%d",&num_input);
for(l=0;l<num_input;l++)
{
char str[100];
char i = 0;
int sq,j,k;
scanf("%s", str);
while(str[i]!='\0')
{
++i;
}
sq = sqrt(i);
if(i== sq*sq)
{
if(i%2==0)
{
for(j=0;j<=i/2;j++)
{
if((str[j]==str[i-j-1])&&(str[j+sq]==str[i-j-sq-1]))
{
if(j==i/2)
{
printf("YES\n");
}
}
else
{ if(j==i/2)
{
printf("NO\n");
}
}
}
}
if(i%2!=0)
{
for(k=0;k<=i/2;k++)
{
if((str[k]==str[i-k-1])&&(str[k+sq]==str[i-k-sq-1]))
{ if(k==i/2)
{
printf("YES\n");
}}
else
{if(j==i/2)
{
printf("NO\n");
}}
}
}
}
else
{
printf("NO\n");
}
}
return 0;
}
The problem of 'mixed' output and input is caused by the fact, that you take one string per calculation. If you want to scan the whole input, then display the output, you should... do exactly that. Simple approach how to do it, given that you know how many strings will be typed:
After you scan the number of strings with int num_input; scanf("%d",&num_input);, you can create a two-dimensional array of characters sized as [num_input][max_str_length]. From your code, I assume that maximal length of each individual string is 100 (given char str[100];).
Then, in a for loop, that loops num_input times, you should scan all your strings and place them in the proper places in your 2D array. This way, your input is stored and ready to be checked by an algorithm. I would encourage you to, instead of writing plain algorith inside of main function, create a function that will take an array and it's size as arguments and return true or 1 when given array contains a string that is a "magic square palindrome" or return false / 0 when it's not. If you do that, you can just loop num_input times again and call your function on currently checked array. Each time the fucntion returns true, you output "YES", otherwise "NO"/
If you don't know anything about 2D arrays and/or making functions yourself, I encourage you to either buy a good C book, or simple google some tutorials, because that stuff is pretty basic and fairly easy to understand.

Printing all duplicate words from a file in C

What am I supposed to do in order to print only the duplicated words in a file. I'm a beginner in C.
Here's my code:
#include <stdio.h>
#define max 100
main(){
FILE *fpointer;
char ch[max],str[max][max];
int i = 0,j = 0,count = 0;
int a,b;
fpointer = fopen("1.txt","r");
if(fpointer == NULL){
printf("Error!");
return 0;
}
while(fscanf(fpointer,"%s",ch)!=EOF){
strcat(str[i++],ch);
strcat(str[i++]," ");
count++;
}
for(a=0;a<count*2;a=a+2){
for(b=0;b<count*2;b=b+2){
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
fclose(fpointer);
return 0;
}
An example of input is "shine little star shine bright in the dark star"
and the output of this program is "shine shine little star star shine shine bright in the dark star star". Please help me to print
only duplicate words. Tnx
In your inner loop, instead of starting at the beginning of the list, start one element after the current one. That way you're not comparing an element against itself or comparing any two elements twice.
for(a=0;a<count*2;a=a+2){
for(b=a+2;b<count*2;b=b+2){ // b=a+2 instead of b=0
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
Output:
shine
star
Since you wrote duplicate words, i am guessing the words in the file will be repeated twice only.
So you second nested for loop is starting from the beginning every time, and thats where the problem is. You have to make sure that the word already checked is not iterated over again. For that you can change your second for loop a little
for(a=0;a<count*2;a=a+2){
for(b=a+2;b<count*2;b=b+2){ //notice b=a+2
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
Note
For cases when the words are repeating more then twice, my suggestion would be to use some hashing technique to store if a word has already occurred or not. And then compare and print accordingly.
You have a couple of problems here.
Go through and write some comments. For example, put these where they belong:
// Open the file
// Read in the strings
// Compare the strings
If you do this you will notice you have some problems. For instance, what is this line for?
strcat(str[i++]," ");
It's not reading in a string. So what is it doing?
In your final loop, you want to compare each string with all the others. So obviously, you start with the first string, and you compare it to all the others:
for (a=1; a<count; a++)
if(strcmp(str[0],str[a])==0)
{
printf("%s\n",str[0]);
break;
}
Now we can compare the first string with each following string and print it out if it is duplicated. The "break" is there so we only print it once.
But this only compares the first string with the others. How do we compare all of them? Another loop, of course.
// Compare each string against all the ones after it
for (target=0; target<count; target++)
for (a=target+1; a<count; a++)
// If the strings match AND they are not both null
// (why print out copies of null strings? - nobody wants that)
if(strcmp(str[target],str[a])==0) && strlen(str[a])
{
// Print it
printf("%s\n",str[target]);
// Why is this here?
strcpy(str[a],"");
for (copies=a+1; copies<count; copies++)
if(strcmp(str[copies],str[target])==0)
strcpy(str[copies],"");
// We got a match, stop checking for this string
break;
}
See how we've got one big loop that steps through each string, and a smaller loop that steps through all the remaining strings (no point in stepping through the ones we already looked at).
Now a question for you: why is "strcpy(str[a],"") and the next for loop in there? What purpose do they serve?
This is one way to do it. Please enable warnings - you left out a library header. I've also checked array limits. You need to find a better way to limit the string input too, than just guess a large array size.
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // included header
#define MAX 100
int main(void){ // correct function
FILE *fpointer;
int reported [MAX];
char ch[MAX], str[MAX][MAX];
int index = 0, a;
fpointer = fopen("1.txt","r");
if(fpointer == NULL){
printf("Error!");
return 0;
}
while(fscanf(fpointer,"%s",ch) == 1){ // testing for 1 item read
for(a=0; a<index; a++){
if(strcmp(ch, str[a])==0){
if (reported[a] == 0) // don't report twice
printf("%s ",ch);
reported[a]++;
break;
}
}
if(a >= index) { // check if loop completed
if (index >= MAX) { // check if array is full
printf("\nToo many words read\n");
exit(1);
}
strcpy(str[index], ch); // word was not found
reported[index] = 0;
index++; // keep tabs on array length
}
}
printf("\n",ch);
fclose(fpointer);
return 0;
}
Program output:
shine star
One issue is that you are storing every word, regardless of whether it has already been seen:
while(fscanf(fpointer,"%s",ch)!=EOF){
strcat(str[i++],ch);
strcat(str[i++]," "); // ??? what is this for
count++;
}
Ideally, you'd only like to store each word once, and maintain a count of how often that word appears in the file:
while ( fscanf( fpointer, "%s", ch ) != EOF ) // whitespace is your friend, use it
{
if ( ch_is_not_already_in_str )
{
strcpy( str[count++], ch );
}
else
{
update_count_for_that_string;
}
}
Then at the end, you just loop through ch and print each string that has a count greater than 1.
for ( i = 0; i < count; i++ )
{
if ( str[i]_occurs_more_than_once )
printf( "%s ", str[i] );
}
The bits you need to figure out are ch_is_not_already_in_str, update_count_for_that_string, and str[i]_occurs_more_than_once. How would you go about searching your str array for an occurence of the string in ch? How would you maintain a counter for each string?

Find longest word C with recursion

I'm trying to find the size of the longest word in an array of structs.
I have this array of structs:
struct Vocabolo{
char parola[20];
char *sinonimi[5];
char definizione[300];
};
typedef Vocabolo vocabolo;
vocabolo parole[30];
Now I have to use incremental recursion in order to find the size of the lognest word in the array. Words are contained each in:
parole[n].parola
I'm using this code:
int Lunghezza_parola(vocabolo *parole,int n){
int y;
if(n == 1)
return strlen(parole[0].parola);
else {
y = strlen(parole[n-1].parola);
return Scegli_max(y,Lunghezza_parola(&parole,n-1));
}
}
Wnere Scegli_max is:
int Scegli_max(int y, int lunghezzaStringa){
if (y >= lunghezzaStringa)
return y;
else
return lunghezzaStringa;
}
In this program the user has to insert words manually and each time a word is inserted, the program should put them in alphabetical order.
If I try to input something like "come" as parole[0].parola and "hi" parole[1].parola and start this function the result is 3. Also it seems to works only if the longest word is in the last position of the array.
Any idea?
PS: this is part of a longer programm so is impossible to write here all the code but i'm quite sure everithing works fine exept this function so the words are ordered correctly in the array of struct.
Your problem is return Scegli_max(y,Lunghezza_parola(&parole,n-1));
You call Lunghezza_parola giving it &parole which is already a vocabolo *parole so this becomes a vocabolo **parole and the pointer is now invalid.
Try changing your return to return Scegli_max(y,Lunghezza_parola(parole,n-1));
Your problem is the line return Scegli_max(y,Lunghezza_parola(&parole,n-1)); . remove the &.
You should pass the value of the pointer, not a pointer to it.

printing data at a array location directly after receiving the two digit address using cbreak(); <curses.h> and getch();

I a a beginner at this, so if this is obvious, take it easy on me.
I am using C.
I am using cbreak(); from curses.h to take input realtime from the Linux terminal.
I am using getch(); to catch one input at a time up to two, and using those inputs to address a 2D array.
What i would LIKE it to be doing is printing data at the array location directly after receiving the two digit address.
As it is, it is taking the first set of two digits, then printing the first array location as it receives the first number of the address of the second location.
Here is what i have:
int northsouth[2]; //array to hold input
int nschoice; //counter for for below
int loopOn = 1;
int northSave; //(confused me) places to save value of northSouth[] in attempt
int southSave; //to print only after receiving two digits.
while(loopOn != 0)
{
for(nschoice = 0; nschoice < 2; ++nschoice)
{
northsouth[nschoice] = getch();
if(nschoice == 1 && northsouth[0] != northSave && northsouth[1] != southSave)
{
strcat(input, l[northsouth[0] -= 48][northsouth[1] -= 48]);
printf("\033[2J\033[1;1H");
printf("%s", input);
northSave = northsouth[0];
southSave = northsouth[1];
}
}
}
If I understood you, you want to print after you read two digits. (not after every one).
If so, you should get the if and its whole block out of the for loop, so the for loop will read 2 digits, and the if will print.

Resources