Having trouble with stack implementation - c

Full disclosure: this is for an assignment. I'm not looking for explicit answers, but a little guidance.
I'm having a hard time initializing my stack in C. Specifically, I can't seem to get it to properly push new elements onto the stack. I know my push/pop/etc functions are correct (they were provided) but I fear that I'm not looking at this correctly.
This is a basic attempt at reading a string and determining if it is "balanced" (all parentheses, curly and square brackets have partners and appear in the correct order.) As far as I can tell, it isn't a problem with my logic and I believe the syntax is correct, so I'm kind of at a loss for ideas...
Here's my attempt at the implementation:
int isBalanced(char* s) {
struct DynArr *string;
string = newDynArr(50);
while (nextChar(s) != '\0') {
if ((nextChar(s) == '(') || (nextChar(s) == '{') || (nextChar(s) == '[')) {
pushDynArr(string, nextChar(s));
}
if (nextChar(s) == ')') {
if (topDynArr(string) != '(') {
return 0;
} else popDynArr(string);
}
if (nextChar(s) == '}') {
if (topDynArr(string) != '{') {
return 0;
} else popDynArr(string);
}
if (nextChar(s) == ']') {
if (topDynArr(string) != '[') {
return 0;
} else popDynArr(string);
}
}
if (isEmptyDynArr(string)) {
printf("The stack is empty\n");
return 1;
} else return 0;
}
The output always prints "The stack is empty" and returns true, despite me giving it unbalanced strings. I've probably been looking at this for too long and can't recognize the obvious. I'd appreciate any help you can lend. I don't need explicit answers, but a push in the right direction would be enough.
Edit: Here are the functions that have been requested...
int isEmptyDynArr(DynArr *v)
{
if(v->size == 0) {
return 1;
}
else return 0;
}
DynArr* newDynArr(int cap)
{
assert(cap > 0);
DynArr *r = (DynArr *)malloc(sizeof( DynArr));
assert(r != 0);
initDynArr(r,cap);
return r;
}
void pushDynArr(DynArr *v, TYPE val)
{
assert(v != 0);
addDynArr(v, val);
}
void popDynArr(DynArr *v)
{
assert(v != 0);
assert(isEmptyDynArr(v) == 0);
v->size--;
}
TYPE topDynArr(DynArr *v)
{
assert(v != 0);
assert(isEmptyDynArr(v) == 0);
return v->data[v->size - 1];
}
char nextChar(char* s)
{
static int i = -1;
char c;
++i;
c = *(s+i);
if ( c == '\0' )
return '\0';
else
return c;
}

this line may skip 1 or 2 or 3 characters from the input line:
nextChar(s) == '(') || (nextChar(s) == '{') || (nextChar(s) == '['
you should most definitely use:
char ch = nextChar(s);
if( ch == '(' || ch == '{' || c == '[' )

You don't seem to be incrementing s anywhere. What does your nextChar function do? I can only guess, but it seems like it'll just return *s. If that's the case, you need to increment s (++s) after each iteration. If it does magically (because there really isn't a sensible way to do that in plain C) increment s anyways, you should only call it once per iteration and save the result. I'd guess it's the former, in which case for example for this string: "(())" you will read the first '(' twice and return 0.
Update: Yeah, apparently your nextChar function does use a global counter. Advice two applies, only call it once per iteration. Or better yet, get rid of that thing. The way that function is designed, you can effectively use it exactly once in the entire lifetime of your program, and the entire functionality of that thing can be replaced by (*s ? *(s++) : *s). Or just *(s++) (and just do the check for 0 yourself).

Related

Is there a way to make my if statement more efficient with an enum?

I am working on a simple parser which takes a string as input and parses a string to see if the opening and closing parentheses/brackets/braces are correctly placed. One step in this involves me skipping every character that is not a valid token (a parenthesis, bracket, or brace), because at this point I don't care whether the expression inside the parentheses are valid or not–I'm only interested in whether the parentheses are syntactically correct. I wrote an if statement which tells the loop to skip to the next iteration when it encounters anything that's not an opening or closing brace, but the code looks ugly and is repetitive. I was wondering if there was a better way to do it–perhaps with an enum. Directly below is the function in question, (parse), and below that, I've pasted the code for the entire program so far. If you answer or attempt to answer this, thank you for your time.
void parse(char *string) {
for (int i = 0; i < strlen(string); i++) {
if (string[0] == ')' || string[0] == ']' || string[0] == '}') {
printf("ParseError: Statement begins with invalid token '%c'", string[0]);
return;
}
if (string[i] != '(' || string[i] != '[' || string[i] != '{' ||
string[i] != ')' || string[i] != ']' || string[i] != '}') {
continue;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char character;
struct Node *link;
} * top;
struct Node *getNewNode(char);
void push(char);
void pop(void);
void parse(char *);
void print(void);
int main() {
top = NULL;
char string[100];
char *string_ptr = string;
printf("Enter an expression to parse: ");
fgets(string, sizeof(string), stdin);
parse(string_ptr);
print();
}
struct Node *getNewNode(char character) {
struct Node *newNode = (struct Node *)(malloc(sizeof(struct Node)));
newNode->character = character;
newNode->link = top;
return newNode;
}
void push(char character) {
struct Node *newNode = getNewNode(character);
top = newNode;
}
void pop(void) {
struct Node *temp;
if (top == NULL) {
printf("Stack is empty!");
return;
}
temp = top;
top = top->link;
free(temp);
temp = NULL;
}
void print(void) {
struct Node *temp = top;
while (temp != NULL) {
printf("%c", temp->character);
temp = temp->link;
}
}
void parse(char *string) {
for (int i = 0; i < strlen(string); i++) {
if (string[0] == ')' || string[0] == ']' || string[0] == '}') {
printf("ParseError: Statement begins with invalid token '%c'", string[0]);
return;
}
if (string[i] != '(' || string[i] != '[' || string[i] != '{' ||
string[i] != ')' || string[i] != ']' || string[i] != '}' ||) {
continue;
}
}
}
There are college courses on parsing theory. We construct software “machines” of various kinds to parse strings, so good solutions for issues like this involve incorporating them into an overall parsing scheme, not solving each one individually.
However, given that, a typical way to handle something like this is to prepare an array with information about the characters:
#include <limits.h>
// Define bit flags for character properties.
enum { IsOpener = 1, IsCloser = 2, };
// Initialize array with flags for characters.
static unsigned CharacterProperties[UCHAR_MAX+1] =
{
['('] = IsOpener,
['['] = IsOpener,
['{'] = IsOpener,
[')'] = IsCloser,
[']'] = IsCloser,
['}'] = IsCloser,
};
…
if (CharacterProperties[string[0]] & IsOpener)
… // Here string[0] is one of the “open parentheses” type of characters.
Note there are some sign issues to watch out for: The subscript to CharacterProperties should be nonnegative, so string should be unsigned char * or you should cast it with (unsigned char) in the subscript or you should ensure char is unsigned. And, if any of the characters in the initialization could be negative (are not in C’s basic execution character set), they should be cast too.
This may be a good use case for a switch:
void parse( char *string )
{
/**
* Make sure string[0] is valid first
*/
switch( string[0] )
{
case ')':
case ']':
case '}':
fprintf( stderr, "parse error..." );
return;
break;
default:
break;
}
/**
* Compute the length of the string once rather
* than every time through the loop.
*/
size_t len = strlen( string );
for ( size_t i = 0; i < len; i ++ )
{
/**
* Is the current character a delimiter?
*/
switch( string[i] )
{
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
// we'll process the delimiter character following
// the end of the switch statement
break;
default:
// this is not a delimiter, go back to the beginning of
// the loop
continue;
break;
}
// process delimiter character
}
}
but that heavily depends on how you're going to process other characters once you beef up your parser. Switches can get ugly and unmaintainable in a hurry. I've written this such that the switches act only as filters; they simply decide whether to proceed with the current operation or not, there's no processing logic in either one.

Inefficiently using strstr and strchr

While reviewing my code, my professor said that my use of strstr and strchr results in a lot of wasted resources as every and each one of them scans the string.
Can I reduce the amount of functions in a good way?
This code scans a string and based on set parameters decides whether the input is valid or not.
ch1 is '#' and ch2 is '.', (email[i]) is the string.
for (i = 0; email[i] != 0; i++) {
{
if (strstr(email, "#.") ||
strstr(email, ".#") ||
strstr(email, "..") ||
strstr(email, "##") ||
email[i] == ch1 ||
email[i] == ch2 ||
email[strlen(email) - 1] == ch1 ||
email[strlen(email) - 1] == ch2) {
printf("The entered e-mail '%s' does not pass the required parameters, Thus it is invalid\n", email);
} else {
printf("The email '%s' is a valid e-mail address\n",email);
}
break;
}
}
This is the snippet I'm talking about.
Should I write my own code that does the checking once? if so, can you give me some pointers in that regards?
thank you.
EDIT: Thank you very much for your responses, I did learn of the mistakes in my code and hopefully I learn from them.
Thanks again!
EDIT:2: I want to thank you again for your responses, they have helped me immensely, and I believe that I have written better code
int at_count = 0, dot_count = 0, error1 = 0, error2 = 0;
int i;
size_t length = strlen(email);
int ch1 = '#', ch2 = '.';
for ( i = 0; email[i] != '\0'; i++) /* for loop to count the occurance of the character '#' */
{
if ( email[i] == ch1)
at_count++;
}
for ( i = 0; email[i] != '\0'; i++) /* for loop to count the occurance of the character '.' */
{
if ( email[i] == ch2)
dot_count++;
}
if ( email[0] == ch1 || email[0] == ch2 || email[length-1] == ch1 || email[length-1] == ch2 )
{
error1++;
}
else
{
error1 = 0;
}
if ( strstr(email,".#") || strstr(email, "#.") || strstr(email, "..") || strstr(email, "##"))
{
error2++;
}
else
{
error2 = 0;
}
if ( (at_count != 1) || (dot_count < 1) || (error1 == 1) || (error2 == 1))
{
printf("The user entered email address '%s' is invalid\n", email);
}
else
{
printf("'%s' is a valid email address\n", email);
}
I feel this is more elegant and simpler code, also more efficient.
My main inspiration was #chqrlie, as I felt his code was very nice and easy to read.
Is there anyway I can improve?
(The email checks are only for practice, don't mind them!)
Thank you very much everyone!
Your code indeed has multiple problems:
for (i = 0; email[i] != 0; i++) { // you iterate for each character in the string.
{ //this is a redundant block, remove the extra curly braces
if (strstr(email, "#.") || // this test only needs to be performed once
strstr(email, ".#") || // so does this one
strstr(email, "..") || // so does this one
strstr(email, "##") || // again...
email[i] == ch1 || // this test is only performed once
email[i] == ch2 || // so is this one
email[strlen(email) - 1] == ch1 || // this test is global
email[strlen(email) - 1] == ch2) { // so is this one
printf("The entered e-mail '%s' does not pass the required parameters, Thus it is invalid\n", email);
} else {
printf("The email '%s' is a valid e-mail address\n", email);
}
break; // you always break from the loop, why have a loop at all?
}
}
You do scan the string 4 times to test the various patterns and another 2 times for strlen(). It should be possible to perform the same tests in the course of a single scan.
Note also that more problems go unnoticed:
there should be a single # present
there should not be any spaces
more generally, the characters allowed in the address are limited.
Some of the tests seem overkill: why refuse .. before the #, why refuse a trailing . before the #?
Here is a more efficient version:
int at_count = 0;
int has_error = 0;
size_t i, len = strlen(email);
if (len == 0 || email[0] == ch1 || email[0] == ch2 ||
email[len - 1] == ch1 || email[len - 1] == ch2) {
has_error = 1;
}
for (i = 0; !has_error && i < len; i++) {
if (email[i] == '.') {
if (email[i + 1] == '.' || email[i + 1] == '#') {
has_error = 1;
}
} else if (email[i] == '#') {
at_count++;
if (i == 0 || i == len - 1 || email[i + 1] == '.' || email[i + 1] == '#') {
has_error = 1;
}
}
// should also test for allowed characters
}
if (has_error || at_count != 1) {
printf("The entered e-mail '%s' does not pass the required tests, Thus it is invalid\n", email);
} else {
printf("The email '%s' is a valid e-mail address\n", email);
}
Your professor has a good point about the inefficiency in repetitively scanning characters in email. Optimally, each character should be scanned only once. Whether you use a for loop and string indexing (e.g. email[i]) or simply walk-a-pointer down the email string is up to you, but you should be locating each character only once. Instead, in your current code you are doing
for every character in email, you
scan email 4-times with strstr to locate a given substring, and
scan to the end of email 2-times with strlen
Think about it. For every character in email, you are calling strlen twice which scans forward over the entire contents of email looking for the nul-terminating character. All four of your strstr calls are locating two character in differing combinations. You could at minimum scan for one or the other and then check the prior character and the one that follows.
#chqrlie points out additional character combinations and conditions that should be checked for, but since I presume this is a learning exercise rather than something intended for production code, it is enough to be aware that additional criteria are needed to make an e-mail validation routine.
While there is nothing wrong with including string.h and for longer strings (generally larger than 32-chars), the optimizations in the string.h function will provide varying degrees of improved efficiency, but there is no need to incur any function call overhead. Regardless what you are looking for in your input, you can always walk down your string with a pointer checking each character and taking the appropriate actions as needed.
A short additional example of that approach to your problem, using the lowly goto in lieu of a error flag, could look something like the following:
#include <stdio.h>
#define MAXC 1024
int main (void) {
char buf[MAXC] = "", /* buffer to hold email */
*p = buf; /* pointer to buf */
short at = 0; /* counter for '#' */
fputs ("enter e-mail address: ", stdout);
if (fgets (buf, MAXC, stdin) == NULL) { /* read/validate e-mail */
fputs ("(user canceled input)\n", stderr);
return 1;
}
while (*p && *p != '\n') { /* check each character in e-mail */
if (*p == '#') /* count '#' - exactly 1 or fail */
at++;
if (p == buf && (*p == '#' || *p == '.')) /* 1st char '# or .' */
goto emailerr;
/* '#' followed or preceded by '.' */
if (*p == '#' && (*(p+1) == '.' || (p > buf && *(p-1) == '.')))
goto emailerr;
/* sequential '.' */
if (*p == '.' && (*(p+1) == '.' || (p > buf && *(p-1) == '.')))
goto emailerr;
p++;
} /* last char '#' or '.' */
if (*(p-1) == '#' || *(p-1) == '.' || at != 1)
goto emailerr;
if (*p == '\n') /* trim trailing '\n' (valid case) */
*p = 0;
printf ("The email '%s' is a valid e-mail address\n", buf);
return 0;
emailerr:;
while (*p && *p != '\n') /* locate/trim '\n' (invalid case) */
p++;
if (*p == '\n')
*p = 0;
printf ("The email '%s' is an invalid e-mail address\n", buf);
return 1;
}
As mentioned there are many ways to go about the e-mail validation, and to a large degree you should not focus on "micro optimizations", but instead focus on writing logical code with sound validation. However, as your professor as pointed out, at that same time your logic should not be needlessly repetitive injecting inefficiencies into the code. Writing efficient code takes continual practice. A good way to get that practice is to write sever different versions of your code and then either dump your code to assembly and compare or time/profile your code in operation to get a sense of where inefficiencies may be. Have fun with it.
Look things over and let me know if you have further questions.
Consider strpbrk. Possibly all conditions can be evaluated with one pass through the email.
#include <stdio.h>
#include <string.h>
int main( void) {
char email[1000] = "";
char at = '#';
char dot = '.';
char *find = NULL;
char *atfind = NULL;
char *dotfind = NULL;
int atfound = 0;
if ( fgets ( email, sizeof email, stdin)) {
email[strcspn ( email, "\n")] = 0;//remove trailing newline
find = email;
while ( ( find = strpbrk ( find, "#."))) {//find a . or #
if ( find == email) {
printf ( "first character cannot be %c\n", *find);
return 0;
}
if ( 0 == *( find + 1)) {
printf ( "email must not end after %c\n", *find);
return 0;
}
//captures .. ## .# #.
if ( dot == *( find + 1)) {
printf ( ". cannot follow %c\n", *find);
return 0;
}
if ( at == *( find + 1)) {
printf ( "# cannot follow %c\n", *find);
return 0;
}
if ( dot == *( find)) {
dotfind = find;
}
if ( at == *( find)) {
atfind = find;
atfound++;
if ( atfound > 1) {
printf ( "multiple #\n");
return 0;
}
}
find++;
}
if ( !atfind) {
printf ( "no #\n");
return 0;
}
if ( !dotfind) {
printf ( "no .\n");
return 0;
}
if ( atfind > dotfind) {
printf ( "subsequent to #, there must be a .\n");
return 0;
}
}
else {
printf ( "problem fgets\n");
return 0;
}
printf ( "good email\n");
return 0;
}

How to debug a Tree Summing and Runtime error?

I am looking at problem 112 from UVa Online Judge.
For a couple of weeks ago, I got some homeworks from my university and the thing is that, though other problems are accepted on the UVa, I cannot figure out what is going wrong with this problem. I've already run the input from Udebug website and there was no problem. I double-checked the result and now, I'm sick and tired of solving this issue.
Here are details about what has happened. First of all, I increase the BUFSIZE to 2^20 in order to avoid any memory overflow. The result? Failed. Second, I downsized the size of the element in the stack I made. The result? Failed. Lastly, I removed an eol character of the result just in case. The result? Failed.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define BUFSIZE 16384
typedef struct node {
int element[BUFSIZE];
int size;
int current;
}Stack;//This is a stack I made
static Stack *stack;
static int level;//This is a level of a node in the whole tree
static int integer;//This is an integer that should be came out from the sum() function
bool initialize(void) {
if (stack == NULL)
stack = (Stack *)malloc(sizeof(Stack));
stack->size = BUFSIZE;
stack->current = 0;
return true;
}
bool push(int number) {
if (stack == NULL)
return false;
if ((stack->current + 1) > stack->size)
return false;
stack->element[stack->current] = number;
stack->current++;
return true;
}
int pop() {
if (stack->current <= 0)
return 0xFFFFFFFF;
stack->current--;
return stack->element[stack->current];
}
int sum() {
int result = 0;
int i;
if (stack == NULL)
return 0xFFFFFFFF;
if (stack->current == 0)
return 0xFFFFFFFF;
for (i = 0; i < stack->current; i++)
result += stack->element[i];
return result;
}//Sum all the values in the stack and return it.
void replace(char * o_string, char * s_string, char * r_string) {
char *buffer = (char *)calloc(BUFSIZE, sizeof(char));
char * ch;
if (!(ch = strstr(o_string, s_string)))
return;
strncpy(buffer, o_string, ch - o_string);
buffer[ch - o_string] = 0;
sprintf(buffer + (ch - o_string), "%s%s", r_string, ch + strlen(s_string));
o_string[0] = 0;
strcpy(o_string, buffer);
free(buffer);
return replace(o_string, s_string, r_string);
}//This is a function I found on Google. Memory usage optimization is not guaranteed.
int main(void) {
char *buffer;
char *line;
char *restOfTheString;
char *token;
bool checked = false, found = false;
int i = 0, j = 0, scannedInteger, result = 0, array[4096];
buffer = (char *)calloc(BUFSIZE, sizeof(char));
restOfTheString = (char *)calloc(BUFSIZE, sizeof(char));
line = (char *)calloc(BUFSIZE, sizeof(char));
memset(buffer, 0, BUFSIZE);
for (i = 0; i < 4096; i++) {
array[i] = -1;
}
level = 0;
integer = 0;
while (fgets(line, sizeof(line), stdin) != NULL) {//Get input line by line
if (line[0] != '\n') {
token = strtok(line, "\n");
if (strlen(line) >= 1) {
strcat(buffer, token);
}
}
}
replace(buffer, " ", "");
replace(buffer, "()()", "K");
strcpy(restOfTheString, buffer);
i = 0;
while (restOfTheString[i] != 0) {
if (level == 0 && !checked) {//If the level of the node is 0, then it is clearly the summed value I need to find out on the whole tree.
initialize();
sscanf(&restOfTheString[i], "%d%s", &integer, &restOfTheString[0]);
i = -1;
checked = true;
}
if (restOfTheString[i] == '(') {
checked = false;
level++;
}//If there is an openning bracket, then increase the level of the node.
else if (restOfTheString[i] == ')') {
if (restOfTheString[i - 1] != '(')
if (pop() == 0xFFFFFFFF)
return 0;
level--;
if (!found && level == 0) {
array[j] = 0;
j++;
free(stack);
stack = NULL;
}//If there is a closing bracket, then it's time to check whether the level of the node is 0. If the level of the node is 0, then we need to report the result to the 'array' which is an integer array and move on to the next input.
else if (found && level == 0) {
array[j] = 1;
j++;
free(stack);
stack = NULL;
found = false;
}
}
else if (restOfTheString[i] == '-' && !checked) {
if (sscanf(&restOfTheString[i], "%d%s", &scannedInteger, &restOfTheString[0]) == 2) {
if (push(scannedInteger) == false)
return 0;
i = -1;
}
}//If there is a minus character, then it's obvious that the next couple of characters are a negative integer and I need to scan it out of the whole input.
else if (restOfTheString[i] >= 48 && restOfTheString[i] <= 57 && !checked) {
if (sscanf(&restOfTheString[i], "%d%s", &scannedInteger, &restOfTheString[0]) == 2) {
if (push(scannedInteger) == false)
return 0;
i = -1;
}
}//If there is a numerous character, then it's obvious that the next couple of characters are a negative integer and I need to scan it out of the whole input.
else if (restOfTheString[i] == 'K') {
if ((result = sum()) == 0xFFFFFFFF)
return 0;
if (result == integer) {
found = true;
}
}//The 'K' character means the integer scanned prior to this iteration is a value in a leaf. So I need to call the sum() function in order to figure it out the result.
i++;
}
i = 0;
while (array[i] != -1) {
if (array[i] == 1)
printf("yes\n");
else if (array[i] == 0)
printf("no\n");
i++;
}
return 0;
}
Though it is clearly suspicious about the memory usage, I don't know how to track the stack on my system.
You use many questionable practices.
You free and re-allocate the stack from scratch. The stack has a fixed size in your case; allocate one at the beginning of main and free once at the end.
You set the index i to −1 as indicator, but keep on accessing restOfString[i] later. restOfString is an allocated string and writing to bytes before the actual data might corrupt the internal information that thze system keeps for allocated memory. This might lead to errors when freeing. In any case, it's undefined behaviour.
You read the input line-wise and concatenate everything into one huge string. You use strcat for this, which will get slower as your string grows. If you must load everything into a large buffer, consider using fread.
Your recursive replace method also does a lot of copying of temporarily allocated buffers.
This:
sscanf(&rest[i], "%d%s", &integer, &rest[0]);
looks fishy. You store the result in the string that you are reading, albeit at different indices. Result and source may overlap, which probably is undefined behaviour. In any case, it entails a lot of copying. Instead of using sscanf, you could read the integer with strtol, which gives you the position of the string after parsing the number. Continue scanning the old string at the resulting offset.
Your problems seem to be not in the core algorithm but with reading the input. Ihe assignment does not mention a maximum line length. This may be a sign that you shouldn't read the input in a line context.
You can use the scanf functions which don't know about line breaks. You can make use of the fact that unsuccessful scanning with data conversion, e.g. scanning an integer, resets the input stream.
Such a strategy would require only storage for the current token. You don't even need a stack if you use recursion. I doubt that the test cases in the online judge will break the stack limit, even if there they contain degenerate trees with a large depths.

Splitting "String" into characters in C

I am taking a beginner's course in C, and trying to wrap my head around "strings". I have previously programmed in Java, so it is a bit confusing.
I am wondering how to split a "string" into characters, so as to be able to remove certain characters. I have written code for a linked list, with each node holding a data value, as well as a next pointer (calling it node_line, as it holds lines).
typedef struct node {
char *data;
struct node *next;
} node_line;
This works without problems, and I can traverse the entire list and print out each element:
void print_list(node_line head) {
node_line * current = head;
while(current != NULL) {
printf("%s\n", current->data);
current = current->next;
}
}
However, I am having problems with converting the "string" in current->data into characters. That is, reading one character at a time.
For instance, I want to write a program that removes all the vowels in a "string". I have managed to solve this when reading a file, using the getc() function. However, I can't seem to do so with the text in current-> data.
int c;
while((c = getc(f)) != EOF) {
//REMOVE
if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') {
printf(""); //Remove the vowel
}
else {
putchar(c); //Write out one character at the time.
}
}
I imagine it being something like:
while ((c = getc(current->data) != NULL) { ... }
Any help, tips, etc. are highly appreciated!
getc is for reading from files. To access chars in a char * buffer (string) you would typically do something like this:
for (const char * p = current->data; *p != '\0'; ++p)
{
char c = *p;
if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') {
...
}
}
Or if you prefer explicit array indexing rather than pointers:
const char * s = current->data;
for (int i = 0; i < strlen(s); ++i)
{
char c = s[i];
if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') {
...
}
}
void print_list(node_line head) {
should be
void print_list(node_line *head) {
getc:
Returns the character currently pointed by the internal file position
indicator of the specified stream.
That's not what you want, use pointer arithmetic:
char *s = current->data;
while (*s) {
if(*s=='a' || *s=='e' || *s=='i' || *s=='o' || *s=='u' || *s=='y') {
printf(""); //Remove the vowel
}
else {
putchar(*s); //Write out one character at the time.
}
s++;
}
or better:
char *s = current->data;
while (*s) {
if(*s!='a' && *s!='e' && *s!='i' && *s!='o' && *s!='u' && *s!='y') {
putchar(*s); //Write out one character at the time.
}
s++;
}

Bracket error matching

I'm trying to get brackets to match. What needs to be matched is the '()', '[]', '{}' and '[{}]' is supposed to output true. I don't want it to work for the cases such as '[{]}' or '[{}'. Though, right now my code is not outputting yes for the correct match even when it should be true.
Code (updated):
int booleanBalanceBracket(aStack *theStack){
aStack *balanceStack = NULL;
while(theStack){
if(theStack->token == '[' || theStack->token == '{' || theStack->token == '(')
balanceStack = pushBracket(theStack->token, balanceStack);
else if(theStack->token == ']' || theStack->token == '}' || theStack->token == ')'){
if(balanceStack == NULL)
return 0;
else
balanceStack = popBracket(balanceStack);
}
theStack = theStack->nextItem;
}
if(balanceStack == NULL){
return 1;
}else{
return 0;
}
}
int isMatching(int token1, int token2){
if(token2 == '(' && token1 == ')')
return 1;
else if(token2 == '{' && token1 == '}')
return 1;
else if(token2 == '[' && token1 == ']')
return 1;
else
return 0;
}
Try this simple algorithm:
for each char c in the input
if opener
push on stack
else if closer
if stack is empty or doesn't match
return false
else
remove top of stack
return true if stack is empty, else false
This can be slightly optimized to avoid the empty stack checks and also to avoid an explicit check for EOF by pushing EOF onto the stack initially, and matching EOF to EOF.
your code problem is this line
balanceStack = popBracket(balanceStack);
Does not receive a value obtained by pop. It is also necessary to compare the value popped.
The Example of a simple string
bool booleanBaranceBracket(const char *s){
static const char *left = "{([";
static const char *right = "})]";
size_t len = strlen(s);
char *p, stack[len];
int sp = -1;
int i;
for(i=0;i<len;++i){
if(p = strchr(left, s[i]))
stack[++sp] = s[i];
else if(p = strchr(right, s[i])){
char ch;
if(sp == -1) return false;
ch = stack[sp--];
if(ch != left[p - right]) return false;
}
}
return sp == -1;
}

Resources