Using Pointer & Scanner to Read Integer Strings

  • Thread starter Firestrider
  • Start date
  • Tags
    Scanner
In summary, the programmer is trying to pass a character pointer to a function which expects a character pointer. However, the programmer is not passing in a pointer, and the program will crash if the pointer is invalid.
  • #1
Firestrider
104
0
What I want to do is pass in a string to read_integer (a function which will parse the string character by character, convert the characters into ints (c - '0'), store it into a struct, and return a pointer to that struct. The string is guaranteed not to be over 200 digits.). I'm not sure how to access part of the struct because the piece that is storing the ints is a int pointer with no array size, and not sure if I'm passing in references right:

Code:
#include <stdio.h>

struct integer 
{
   int* digits;
   int size;
};

struct integer* read_integer(char* stringInt);

int main(void)
{
   FILE* read_file;
   char intStr[200];
   struct integer* first;

   read_file = fopen("ints.txt", "r");
   fscanf(read_file, "%s", &intStr);
   first = read_integer(intStr);
   
   fclose(read_file);
   system("PAUSE");
   return 0;
}

struct integer* read_integer(char* stringInt)
{
       int index;
       struct integer* new_integer;
       char iterchar;
       
       new_integer = (struct integer*)(malloc(sizeof(struct integer)));
       new_integer->size = strlen(stringInt);
       new_integer->digits = (int*)(malloc(new_integer->size * sizeof(int)));
       
       for(index = 0; index < new_integer->size; index++)
       {
          scanf("%c", &iterchar);
          new_integer->digits = (int)(iterchar - '0');
          printf("%c", iterchar);
       }
       
       return new_integer;
}
 
Technology news on Phys.org
  • #2
First off, if you don't check for a valid pointer after attempting to allocate heap memory the program will crash if you use the pointer. Secondly, when you return from read_integer(), you are not deallocating any heap memory potentially allocated, so this will cause a memory leak if you succeed. Before figuring out the logic, you should understand and implement the basics of good housekeeping.

You can figure out what a character is relative to a digit by looking at the code page you are writing to. Usually, the digit '32' will convert between the two but not all the time.
 
  • #3
1. How do I check for a valid pointer?
2. Should I free(new_integer) and free (new_integer->digits) after returning new_integer?
3. How can I store parsed characters to new_integer->digits?
4. Is any syntax or parameter passing wrong so far in my example?
 
  • #4
(1) if (pAllocatedHeapMemory == NULL)
....handle no memory available condition

(2) You should reclaim all memory you allocated

(3) Look at your code page you are writing to. What is the difference between an 'A' (or an 'a') and a '0'?

(4) You are only passing one parameter...a char pointer. It looks OK, just make sure the memory of the characters are sequential.


As a side note, I generally do not like to allocate memory like you are. One method allocates and another deallocates. It may be better if you pass a pointer to the 'Scan' method in the form of a valid struct pointer and allocate the memory of the struct before the call instead of in the call.
 
  • #5
In the main function I'm declaring char intStr[200]; and first = read_integer(intStr); but the function struct integer* read_integer(char* stringInt) requires a character pointer, and I'm not passing in a pointer, this is fine?

Also would this work for converting/storing in ints if stringInt is guaranteed to have character glyph 1 through 9:

Code:
  struct integer* read_integer(char* stringInt)
{
   int index;
   struct integer* new_integer;
   
   new_integer = (struct integer*)(malloc(sizeof(struct integer)));
   new_integer->size = strlen(stringInt);
   new_integer->digits = (int*)(malloc(new_integer->size * sizeof(int)));
       
   for(index = 0; index < new_integer->size; index++)
   {
      new_integer->digits = (int)(stringInt[index] - '0');
   }
       
   return new_integer;
   
   free(new_integer);
   free(new_integer->digits);
}
 
  • #6
You are passing a pointer...a pointer to the first memory address in the array. This appears OK. As a rule, I never use a passed in pointer until I check it for validity because someone else may have wrote the other code, or I may have made an undiscovered error previously. Either way, the program will crash if using an invalid pointer. Your free() calls are not invoked. As I mentioned before, I would not worry about your logic until you learn how to implement good housekeeping. When you get to the logic, look at your code page.

Do you have a debugger
?
 
  • #7
Thanks for your help.

I don't know what you mean by code page, do you mean ASCII table?

I'm using DevC++ IDE and the program compiles and runs ok, but on run-time I get an error in the console: C:\Users\Sean\Documents\bigint.c [Warning] assignment makes pointer from integer without a cast on the line: new_integer->digits = (int)(stringInt[index] - '0');

This is for a computer science class teaching us the basics of structs, pointers, and dynamic memory allocation... this is the first program and it seems really hard for me.

What do you mean my free() calls are not invoked, does the program not get that far in run-time?
 
  • #8
You are returning before the free() calls are invoked. Even if they were invoked you would be returning a NULL pointer since you are trying to free the memory. I realize you are attempting to follow my thoughts by placing the allocation and deallocation in the same method. You might try allocating and deallocating the memory in the main() method and then send as a parameter a pointer to the struct. If you did this, you could just return a boolean value representing failure or success. Generally, there is no need for another method unless you intend to share the method with other code or you are building a library.

You could be supporting ACSII, ANSI, UNICODE, etc. and the libraries you have at your disposal (such as a call to atoi()) would depend upon the logic needed to parse a character and convert to an integer. So far, you have not dislosed this, unless I missed it.

I use Visual C++ so I am guessing here. The warning of your compiler sounds like you are not casting the '0'. Does this give you a warning?

new_integer->digits[nIndex] = (int)((char)stringInt[index] - (char)'0');

If it still does, play around with the parenthesis. It sounds like you are missing a cast.

Overall, the main thing is to keep being persistent. These computers are very dumb. You just have to figure out the leverage.
 
Last edited:
  • #9
Potential said:
First off, if you don't check for a valid pointer after attempting to allocate heap memory the program will crash if you use the pointer. Secondly, when you return from read_integer(), you are not deallocating any heap memory potentially allocated, so this will cause a memory leak if you succeed. Before figuring out the logic, you should understand and implement the basics of good housekeeping.
What's with the italics? Are you trying to make your responses hard to read?

Logic is more important than housekeeping in introductory programming problems, which this appear to be. By harping on housekeeping, Potential, you missed the bigger problem (bolded below).

Firestrider said:
1. How do I check for a valid pointer?
2. Should I free(new_integer) and free (new_integer->digits) after returning new_integer?
3. How can I store parsed characters to new_integer->digits?
4. Is any syntax or parameter passing wrong so far in my example?

1. malloc returns the NULL pointer to indicate failure. It is a good idea to check for failure in calling any routine that can fail.

2. No. If you do that you cannot access the contents. You *should* free allocated memory when you are done using it. You *must not* free allocated before you are done using it.

3. The statement new_integer->digits = (int)(iterchar - '0'); is the key source of your problems. You allocated the space earlier. This statement overwrites the earlier assignment. Now you need to use that allocated space by assigning into new_integer->digits rather than assigning to new_integer->digits.

4. Your definition of and use of read_integer are fine.Your use of free in the revised version (post #5) is not valid. Fortunately, that code will never execute (it is after the return statement).
 
  • #10
D H said:
3. The statement new_integer->digits = (int)(iterchar - '0'); is the key source of your problems. You allocated the space earlier. This statement overwrites the earlier assignment. Now you need to use that allocated space by assigning into new_integer->digits rather than assigning to new_integer->digits.

Yeah, I don't know how to assign into this int* digits when dealing with pointers and structures. new_integer->size = strlen(stringInt) works.

Can you give me an example?

Thank you.
 
  • #11
The allocated memory is essentially an array. How do you set the nth element of an array?
 
  • #12
Would this work:

Code:
new_integer->digits[index] = (int)(stringInt[index] - '0');

It seems that I have a NULL pointer or something because when I try to print:

Code:
first = read_integer(integer_string);
print(first);

void print(struct integer* p)
{
   int index;
   
   for(index = 0; index < p->size; index++)
   {
      printf(p->digits[index]);
   }
}

The program crashes.
 
  • #13
Firestrider said:
Would this work:

Code:
new_integer->digits[index] = (int)(stringInt[index] - '0');
Yes.

It seems that I have a NULL pointer or something because when I try to print:

The program crashes.
I'm going to repeat something Potential asked in post #6: Do you have a debugger?
 
  • #14
Thanks for all the help guys.

I got the read_integer and print_integer functions working like I want.

I got a question though,

1. What lib do I need for max(a,b) to work? I get linker errors when doing this: int carry[max(p->size, q->size)];
 
  • #15
When I call this function and print it returns a negative large integer. Every single time I compile and run the number changes. Can you see any logical errors in this:

Code:
struct integer* add(struct integer* p, struct integer* q)
{
   int index;
   int max;
   
   if (p->size > q->size)
   {
      max = p->size;
   }
   else if (q->size > p->size)
   {
      max = q->size;
   }
   else
   {
      max = p->size;
   }

   int carry[max];
   struct integer* result;
   
   result = (struct integer*)(malloc(sizeof(struct integer)));
   result->size = max + 1;
   result->digits = (int*)(malloc(result->size * sizeof(int)));
   
   for(index = 0; index < result->size; index++)
   {
      if (carry[index] + p->digits[index] + q->digits[index] >= 10)
      {
         carry[index + 1] = 1;
         result->digits[index] = carry[index] + p->digits[index] + q->digits[index] - 10;
      }
      else if (carry[index] + p->digits[index] + q->digits[index] < 10)
      {
         carry[index + 1] = 0;
         result->digits[index] = carry[index] + p->digits[index] + q->digits[index];
      }
   }
   
   return result;
}
 
  • #16
To answer your previous question, max is not in the C standard library. You can find it defined (non-standard) as a macro MAX, sometimes in math.h (but no promises; it's not standard).

I'll answer your latter question with a hint and a question. The hint: "Every single time I compile and run the number changes." That almost always means a problem with uninitialized memory. The question: Do you have a debugger, and do you to use it?
 
  • #17
What is weird is that half of the large integer is the correct answer I want, and half of it is some random integer.

I looked through all my code and can't find something I did not initialize.

My IDE has a debugger but I don't know how to use it, I usually debug by putting in printf() functions.
 

1. What is a pointer in programming?

A pointer is a variable in programming that stores the memory address of another variable. It allows the programmer to directly access and manipulate the referenced variable's value, making it a powerful tool for managing memory and creating more efficient code.

2. How do I use a pointer to read an integer string?

To use a pointer to read an integer string, you first need to declare a pointer variable and assign it the address of the string using the & operator. Then, you can use the pointer to access each character in the string and convert it to an integer using the atoi() function.

3. What is a scanner in programming?

A scanner is a class in programming that allows you to read user input from the console or other input sources. It provides methods for reading different types of data, including strings, integers, and floating-point numbers, making it a useful tool for creating interactive programs.

4. How do I use a scanner to read an integer string?

To use a scanner to read an integer string, you first need to create an instance of the scanner class and pass the input source as a parameter. Then, you can use the nextInt() method to read the next integer value from the input source. If the input is not an integer, it will throw an exception, so make sure to handle that in your code.

5. Can I use both a pointer and a scanner to read an integer string?

Yes, you can use both a pointer and a scanner to read an integer string. The pointer can be used to directly access and manipulate the string, while the scanner can be used to read user input. You can also use the scanf() function in C or cin in C++ to read integer strings, making it a versatile approach to reading user input in programming.

Similar threads

  • Programming and Computer Science
Replies
7
Views
1K
  • Programming and Computer Science
Replies
5
Views
872
  • Programming and Computer Science
Replies
5
Views
1K
Replies
10
Views
951
  • Programming and Computer Science
Replies
12
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
1K
Replies
20
Views
9K
  • Programming and Computer Science
Replies
4
Views
2K
  • Programming and Computer Science
Replies
32
Views
2K
  • Programming and Computer Science
Replies
23
Views
1K
Back
Top