How to extract whole words from char array

I have to read a text file of words into a stack and queue in order to check if hey are palindromes. I'm not allowed the use of string so I'm reading the text into a character array. Everything works, I just don't know how to read the file word for word in order to compare the stack to the queue.
This is the input file:
-------------------------------
madam
Madam I'm Adam.
A man, a plan, a canal, Panama!
Never odd or even
Amor, Roma
race car
step on NO pets
Able was I, ere I saw Elba
$$$$$
--------------------------------
And this is my code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  #include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>

using namespace std;
struct Node{
	char data;
	Node *next;
};

struct Stack{
	Node *top;
};

struct Queue{
	Node *front;
	Node *rear;
};

Stack *initStack(){
	Stack *s;
	s=(Stack*)malloc(sizeof(Stack));
	s->top=NULL;
}

Queue *initQueue(){
	Queue *q;
	q=(Queue*)malloc(sizeof(Queue));
	q->front=NULL;
	q->rear=NULL;
return q;
}

bool isEmpty(Queue *q){
	return (q->front==NULL);
}

bool isEmpty(Stack *s){
	return (s->top==NULL);
}

Node *createNode(char c){
	Node *newNode;
	newNode=(Node*)malloc(sizeof(Node));
	newNode->data=c;
	newNode->next=NULL;
return newNode;
}

Node *insertAtHead(Node *top, char c){
	Node *newNode;
	newNode= createNode(c);
	newNode->next=top;
	top=newNode;
return top;
}

Node *deleteAtHead(Node *top){
	Node *curr;
	curr=top;
		if(top==NULL)
			return NULL;
		else{
			curr=top;
			top=top->next;
			free(curr);
			return top;
		}
}

void push(Stack *s, char c){
	s->top=insertAtHead(s->top, c);
}

char pop(Stack *s){
	char c;
	Node *top;
		if(isEmpty(s)){
				cout<<"Stack is Empty";
				return 'X';
			}
		top=s->top;
		c=top->data;
		s->top=deleteAtHead(s->top);
	return c;
}

char peek(Stack *s){
	char c;
	Node *top;
		if(isEmpty(s)){
			cout<<"Stack is Empty";
			return 'X';
		}	
		top=s->top;
		c=top->data;
	return c;
}
void enqueue(Queue *q, char c){
	Node *newNode= createNode(c);
		if(isEmpty(q)){
			q->front=newNode;
			q->rear=newNode;
		}else{
			q->rear->next=newNode;
			q->rear=newNode;
		}

}

char dequeue(Queue *q){
	char hold = q->front->data;
	Node *temp=q->front;
	q->front=q->front->next;
		if(q->front==NULL)
			q->rear=NULL;
	free(temp);
	return hold;
}

bool isUpperCase (char c) {
 if (c >= 'A' && c <= 'Z')
 return true;
 return false;
} 

char toLower(char ch ){
 if (isUpperCase(ch))
 ch = ch + 32;
 return ch;
} 

int main(){
    ifstream in;
    in.open("input2.txt");
    int i=0;
    int num=0;
    char ch[100];
    char c;
    
    Queue *q;
    q=initQueue();
    Stack *s;
    s=initStack();
    
    in>>c;
    	while(c!='$'){
    		c=toLower(c);
    		enqueue(q, c);
    		push(s, c);
    		ch[i] = c;
    		i=i+1;
    		in>>c;
    		num=num+1;
		}
	in.close();
    return 0;
}
You should only add alphabetic characters to your containers. The standard library header <cctype> has tolower and isalpha prototypes.
1
2
3
4
5
6
7
8
9
while (c != '$') {
    if (isalpha(c)) {
        c = tolower(c);
        equeue(q, c);
        push(s, c);
        ch[i++] = c;
    }
    in >> c;
}

num is the same as i so I left it out.
Hello ElleJay,

Been working with your program a bit and I find this:
so I'm reading the text into a character array
partially correct. You do read into "ch" which is an array, but also into "q" ans "s" which are linked lists. It all works, but I do not think that is what you wanted.

What I think I might do is to use the "ch" array to store a word then call a function that would reverse the letters into a temp array then compare the two arrays maybe returning a bool from the function.

Your next problem is having to deal with multiple words in one line along with ","s in some of the lines. Doable just needs some extra checking.

I think you have over thought this and are making it harder than it needs to be.

You may want to start with reading the file and extracting the words to work with. Yo might consider a 2D array to store each word char arr[20][20]{};. This will give you twenty lines, e.g., 20 words and the second dimension would be the character array for each word. The 20s are just an idea they can be any number that you would need.

This is not perfect, but an idea of what you can do that seemed to work a little better:

1
2
3
4
5
6
7
8
9
10
11
12
13
in >> c;

while (c != '$'  && c != '\n')  // <--- Added second part.
{
	c = toLower(c);
	std::cout << c << ' ';
	enqueue(q, c);
	push(s, c);
	ch[i] = c;
	i = i + 1;
	in.get(c);  // <--- Changed to work with while condition,
	num = num + 1;
}


Hope that helps,

Andy
If I were to use the 2d array, how would I enter the information into it? I've only just started that topic. So far, what you have given me works amazingly, but for only the first line.


1
2
3
4
5
6
7
8
9
10
11
12
13
char ch[100][20];

in>>c;
  	while(c!='$' && c!= '\n'){
    		c=toLower(c);
    		cout<<c;
    		enqueue(q, c);
    		push(s, c);
    		ch[i] = c;
    		    		i=i+1;
    		in.get(c);
    		num=num+1;
		}


Also, the stacks and queues are part of the question I'm doing, since stacks would store the string in reverse so I can do the comparison with the queue:

1
2
3
4
5
 while((!isEmpty(q))&&(!isEmpty(s))){
		if(q->front!=s->top)
		      palindrome=false;
	}
 

Last edited on
Hello ElleJay,

You could use a 2D array, but why? what did you have in mind?

The only reason I can see for a 2D array is to read a whole line and break it up into the different words where each row would be a different word.

My thoughts have been using a 1D array in place of the linked lists, which seems a little much just to store a letter, then in a function create a temp array to reverse the order before comparing the two arrays.

What you have appears to work as long as you go through the linked lists in the right order.

Right now my problem is breaking down a line with several words into single words. Something I can easily do with strings, but your way is something I am not use to.

Hope that helps,

Andy
I was hoping to use the 2d array, for eg) char array[100][50]: 100 is the no. of sentences and 50 is the length of the sentence. This question requires that I use linked lists. The array is for storing the sentences in a format that would be easily read into my stack and queue.
Hello ElleJay,

That should work at least for testing. Although it may not be allowed in the final version for the assignment. Doing this should give you some ideas of how to just read the file for what you need.

Andy
closed account (SECMoG1T)
so i thought i could help you understand how you could use a queue and a stack, well my code isn't well written but you look at it and you'll get the point.

Note: i haven't used your stack and queue implementation , you can substitute that.
: i also understand that you don't want to use std::string

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cctype>
#include <queue>
#include <stack>

void readNCompare();

int main()
{
    readNCompare();
}

void readNCompare()
{
    std::ifstream _filestream("test.txt");

    if(_filestream)
    {
        std::stack<char> _cstack;
        std::queue<char> _cqueue;
        const int MAXSIZE = 100;
        char buffer[MAXSIZE]{};
        const char NULLCHAR = '\0';


        while(_filestream.getline(buffer,MAXSIZE,'\n') &&  buffer[0] != '$') ///read one line assuming its <= MAXSIZE characters
        {
            bool _lineIsPalidrome = true;
            int  _index = 0;
            char _temp = buffer[_index];

            std::cout<<std::left;
            std::cout<<std::setw(30)<<buffer;

                                                         ///loading loop: load alphanums into queue and stack
            while(_index < MAXSIZE && _temp != NULLCHAR) ///load each line into queue and stack
            {
                if(std::isalnum(_temp))                  ///check only digits and alpha characters
                {
                    _temp = std::tolower(_temp);        ///only store lower case
                    _cstack.push(_temp);
                    _cqueue.push(_temp);
                }

                ++_index;
                _temp = buffer[_index];
            }

                                                       ///comparison loop: checks for palidromes
            while(!_cstack.empty() && _lineIsPalidrome)///stack and queue are same size, if stack is empty queue == empty
            {
                if(_cstack.top() != _cqueue.front()) ///any mismatch found along makes the line !palidrome
                {
                    _lineIsPalidrome = false;
                    _cstack = {};
                    _cqueue = {};
                }

                _cstack.pop();
                _cqueue.pop();
            }


            std::cout<<":  is ";

            if(_lineIsPalidrome)
                std::cout<<"palidrome\n";

            else
                std::cout<<"not palidrome\n";
        }

        std::cout<<"\n\n\t!!!!!!!!!!!!!!The End!!!!!!!!!!!\n\n";
    }

    else
        std::cout<<"failed to open your file\n";
}


hope that helps.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <stack>
#include <queue>
#include <cstring>
using namespace std;

bool isPalindrome( const char *p )
{
   stack<char> S;
   queue<char> Q;

   for ( ; *p; p++ )
   {
      char c = *p;
      if ( isalpha( c ) )
      {
         c = tolower( c );
         S.push( c );
         Q.push( c );
      }
   }

   while ( !S.empty() )
   {
      if ( S.top() != Q.front() ) return false;
      S.pop();
      Q.pop();
   }

   return true;
}


int main()
{
   const char *sentences[] = { "ABCccba",
                               "Able was I ere I saw Elba",
                               "Nightingale" };

   for ( auto s : sentences ) cout << "\"" << s << "\"" << ( isPalindrome( s ) ? " is " : " is not " ) << "a palindrome\n";
}

Last edited on
Topic archived. No new replies allowed.