Alphabetical comparison of two strings in C - c

My programming experience is extremely scattered and I can't seem to find the answer to what I hope is a simple question. I had an assignment last week that I didn't properly finish and it's bugging me to death.
I was supposed to compare two strings alphabetically without using strcmp and find out which string is alphabetically first via a function using pointers.
int strcmp373(char *str1, char *str2) {
while(*str1 != '\0')
{
str1++;
}
while(*str2 != '\0')
{
str2++;
}
if(*str1 == *str2)
}
This is my horrible attempt, my thought process being to use the null terminated value. I was hoping I could get some insight and explain how it works?
Here's a copy of the assignment specifications for reference.
Write a function called strcmp373, which compares two strings in precisely the same way that strcmp does in the C library . This time, please use "pointer syntax" in writing this function. That is, the [ ] operator should not be used at all when referring to particular characters in string1 and string2; instead, all parameters and local variables should be declared as pointers (using the * symbol). Please be sure that you emulate the strcmp C function. Note that strcmp returns 0 if the two strings are equal, even though 0 normally means false in C. The sign of other return values matters is used to indicate in what way the strings are not the same, but the precise return value is not important.
You may not use any of the built-in C string library functions to complete this code.
Here is the prototype of this function:
int strcmp373(char *, char *);
And here is a main function which you can use to test strcmp373.
#include <stdio.h>
#include "hw3.h" // to be discussed
int main() {
char str1[81], str2[81];
char again = 'y', newline;
while (again == 'y') {
printf("Enter a string\n");
scanf("%s", str1);
printf("Enter another string\n");
scanf("%s", str2);
int comp = strcmp373(str1, str2);
if (comp < 0)
printf("%s is alphabetically before %s\n", str1, str2);
else if (comp > 0)
printf("%s is alphabetically after %s\n", str1, str2);
else printf("%s and %s are the same\n", str1, str2);
printf("Again? (y/n)\n");
scanf("%c%c", &newline, &again);
}
}

Let's say str1 points to something that holds "abcd" and str2 points to something that holds "abc".
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
When you execute
while(*str1 != '\0')
{
str1++;
}
You move str1 until it points to the null character.
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
Similarly, when you execute
while(*str2 != '\0')
{
str2++;
}
You move str2 until it points to the null character.
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
When the while loops are done, both str1 and str2 point to a null character. Hence, *str1 == *str2 always evaluates to true.
What you need is to compare *str1 and *str2 and then increment them together if they are equal until they are not equal or you reach the end of the strings.
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
str1
|
v
+---+---+---+---+----+
| a | b | c | d | \0 |
+---+---+---+---+----+
str2
|
v
+---+---+---+----+
| a | b | c | \0 |
+---+---+---+----+
Now that you know they are not equal and 'd' is greater tha '\0' return a positive value indicating the LHS is alphabetically greater than the RHS.
That logic can be implemented using:
while ( *str1 != '\0' && *str1 == *str2 )
{
++str1;
++str2;
}
return (*str1 - *str2);

if(*str1 == *str2)
You have an if statement with no body in your code excerpt.
Apart from that your program is counting the amount of characters in the character array passed to that function. This won't really achieve your goal.
Lets call each char array a word. What you want to do is find which 'word' comes first in the alphabet. I suggest looking at an ASCII table.
Each letter in either word has a corresponding ASCII number value. If you can figure out how to access the number value of each of these letters, you can compare the strings and the lower value will be higher up in the alphabet.
Unless they are capitalized. That will require a little more work. Here is an ASCII table where you can see the difference.
This will get you started with figuring out how to get the ASCII value of these letters

Related

Why does accessing an array of pointers de-references the pointer of the pointer?

I cannot understand this unexpected C behavior where printing argv[0] prints ./a.out instead of the actual content of argv[0] which should be a memory address because argv is an array of pointers.
If I create an array called char name[] = "hello" then I would expect to see h at name[0] and if char * argv[] holds, for example 3 pointers (memory addresses) then logically argv[0] should be a memory address.
My reasoning is that if I wanted to access the actual content of the memory address that argv[0] points to I should need to do *(argv[0]). What is happening here? Is C doing some kind of magic here?
+------+------+------+---+---+----+
| h | e | l | l | o | \0 |
+------+------+------+---+---+----+
^---- name[0] = h
+------+------+------+
| 0xA7 | 0xCE | 0xC4 |
+------+------+------+
^---- argv[0] = should be 0XA7 (the value of `argv[0]`,
not the value it points to
#include <stdio.h>
int main(int argc, char * argv[]) {
char name[] = "hello";
printf("%c \n", name[0]); // expected h
printf("%s \n", argv[0]); // expected 0xA7 (but got ./a.out instead)
}
$ gcc main.c
$ ./a.out arg1 arg2 arg3
My reasoning is that if I wanted to access the actual content of the memory address that argv[0] points to I should need to do *(argv[0]). What is happening here?
printf is doing the dereferencing. When passed "%s" and a pointer (address), printf doesn't print the address. It prints what's at the address. Specifically, it prints ptr[0], ptr[1], ptr[2] etc until a zero is encountered.
(Keep in mind that ptr[i] is identical to *(ptr+i). I'm going to use the former since it's cleaner.)
Let's start with a simpler example.
char *name = "hello";
printf( "%s", name );
name
+-------------------+ +-----+-----+-----+-----+-----+-----+
| [Some address 1] -------->| 'h' | 'e' | 'l' | 'l' | 'o' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+-----+
Passing "%s", name passes the address of an array containing %s␀ and the address contained by name ("[Some address 1]"). The latter is the address of an array containing hello␀.
This tells printf to print name[0] (h), name[1] (e), name[2] (l), etc until a zero is encountered.
Now let's look at your case.
argv
+-------------------+ +-------------------+ +-----+-----+-----+-----+-----+-----+-----+-----+
| [Some address 2] -------->| [Some address 3] -------->| '.' | '/' | 'a' | '.' | 'o' | 'u' | 't' | 0 |
+-------------------+ +-------------------+ -----+-----+-----+-----+-----+-----+-----+-----+
| [Some address 4] -------->| 'a' | 'r' | 'g' | '1' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+
| [Some address 5] -------->| 'a' | 'r' | 'g' | '2' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+
| [Some address 6] -------->| 'a' | 'r' | 'g' | '3' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+
| NULL |
+-------------------+
or just
argv[0]
+-------------------+ +-----+-----+-----+-----+-----+-----+-----+-----+
| [Some address 3] -------->| '.' | '/' | 'a' | '.' | 'o' | 'u' | 't' | 0 |
+-------------------+ +-----+-----+-----+-----+-----+-----+-----+-----+
Passing "%s", argv[0] passes the address of an array containing %s␀ and the address contained by argv[0] ("[Some address 3]"). The latter is the address of an array containing ./a.out␀.
This tells printf to print argv[0][0] (.), argv[0][1] (/), argv[0][2] (.), etc until a zero is encountered.
%s tells printf “Load characters from the address you are passed and print the characters from there until you find a null character.”
With %s, printf does not print or format the address it is passed. It uses the address to access memory.
For an array declared like:
char name[] = "hello";
the expression name[0] has the type char and by using the conversion specifier c in the call of printf:
printf("%c \n", name[0]);
the first element of the array is outputted as a character.
This declaration of an array:
char * argv[]
that is used as a parameter declaration is adjusted by the compiler to the declaration:
char **argv
and the expression argv[0] has type char *.
The conversion specifier s is designed to output strings pointed to by corresponding arguments like this:
printf("%s \n", argv[0]);
argv[0] points to a string that contains the name of the program that runs.
If you want to output the expression as an address you need to write:
printf("%p \n", ( void * )argv[0]);
To make it more clear consider this statement:
printf( "%s\n", "Hello" );
Its output I think you are expecting is:
Hello
The string literal has the type char[6]. But using as an expression in the call of printf it is implicitly converted to pointer to its first element of the type char *.
So the second argument of the call of printf has the type char * the same way as in the call:
printf("%s \n", argv[0]);
where the second expression also has the type char *.

Confusion on how to use strchr in C

char *strchr( const char *s, int c );
I understand that strchr locates the first occurrence of character c in string s. If c is found, a pointer to c in s is returned. Otherwise, a NULL pointer is returned.
So why does below code outputs num to strlen(string) rather than what its designed to do?
num=0;
while((strchr(string,letter))!=NULL)
{
num++;
string++;
}
But this code gives correct output
num=0;
while((string=strchr(string,letter))!=NULL)
{
num++;
string++;
}
I fail to see why assigning the pointer that's returned to another qualified pointer even makes a difference. I'm only just testing if return value is a NULL pointer or not.
string is a pointer.
In the first example, you just move it right one position, regardless of where (or if!) "letter" was found.
In the second example, every time you find a "letter", you:
a) update "string" to point to the letter, then
b) update "string" again to point just past the letter.
Let me try to put it in different way,
strchr
returns a pointer to the located character, or a null pointer if the character does not occur in the string.
In first part of your snippet return value is not being captured, immediate next position of string from where earlier it was pointing is passed as a argument.
In short the snippet is counting total number of character till last appearance of letter
const char* string = "hello"
char letter = 'l'
num=0;
while((strchr(string,letter))!=NULL)
{
num++;
string++;
}
Like this,
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
^
|
+-------+ |
+string +-----+
+-------+
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
^
|
+-------+ |
+string +---------+
+-------+
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
^
|
+-------+ |
+string +-------------+
+-------+
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
^
|
+-------+ |
+string +---------------------+
+-------+
In second snippet, return value of strchr is captured back into string and immediate next address is passed as argument in next iteration,
const char* string = "hello"
char letter = 'l'
num=0;
while((string = strchr(string,letter))!=NULL)
{
num++;
string++;
}
Something like this,
+-------+
+string +-----+
+-------+ |
|
/*input pointer to strchr*/
|
v
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
|
|
/*return pointer from strchr*/
|
+-------+ |
+string +<------------+
+-------+
+-------+
+string +-----------------+
+-------+ |
|
/*input pointer to strchr*/
|
v
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
|
|
/*return pointer from strchr*/
+-------+ |
+string +<----------------+
+-------+
+-------+
+string +---------------------+
+-------+ |
|
/*input pointer to strchr*/
|
v
+---+---+---+---+---+----+
|'h'|'e'|'l'|'l'|'o'|'/0,|
+---+---+---+---+---+----+
/*NULL return from strchr*/
+-------+ |
+string +<--------------------+
+-------+
First code snippet:
So why does below code outputs num to strlen(string) rather than what its designed to do?
The output may not be strlen(string) always and will be depend on the input string string and the character letter passed to strchr(). For e.g. if the input is
string = "hello"
letter = 'l'
then the output you will get is 4 which is not equal to the length of string "hello". If the input is
string = "hello"
letter = 'o'
then the output you will get is 5 which is equal to the length of string "hello". If the input is
string = "hello"
letter = 'x'
then the output you will get is 0.
The output is actually depends on the position of last occurrence of the character letter in the input string.
Reason is that there is only one statement which is modifying the position of string pointer and that statement is
string++;
It is working in this way -
If the character present in the string, the strchr() will return a not null value till the time the input string pointer point to a character on or before the last occurrence of character letter in the string. Once string pointer point to one character after the last occurrence of letter character in the string, the strchr() will return NULL and loop exits and num will be equal to position of the last occurrence of letter character in the string. So, you will get the output within the range from 0 to strlen(string) and not strlen(string) always.
string = "hello", letter = 'e', num = 0
strchr(string, letter) will return not null as 'e' present in input string
num++; string++;
string = "ello", letter = 'e', num = 1
strchr(string, letter) will return not null as 'e' present in input string
num++; string++;
string = "llo", letter = 'e', num = 2
strchr(string, letter) will return null as it does not find 'e' in input string and loop exits
Output will be 2
Second code snippet:
But this code gives correct output
Yes, the reason is the strchr() returned pointer is assigned to string pointer. Take the same example as above, assume the input is
string = "hello"
letter = 'l'
strchr(string, letter) will return the pointer to first occurrence of character l and it is assigned to pointer string. So, now the string pointer pointing first occurrence of l. Which means, now the string is
string = "llo"
and in loop body you are doing
string++;
which will make the string pointer point to next character to the character returned by strchr(). Now the string is
string = "lo"
letter = `l`
and strchr(string, letter) will return the pointer to character which the string is pointing to currently as it is matching to character letter. Due to string++ in the loop body, now the string will point to next character
string = "o"
letter = `l`
and strchr(string, letter) will return NULL and loop will exit. num is incremented as many times as the character letter found in string. Hence the second snippet is giving correct output.

Does a 1D array work as a list of strings, or a single string?

#include <stdio.h>
#include <string.h>
int main()
{
int i;
char a[10];
for(i=0;i<10;i++)
{
scanf("%s",a);// >how this line is working in memory.
}
return 0;
}
In the above code, I would like to know how the string is saved in memory, since I have initialised it as a 1D character array, but does the array work as a list of strings, or a single string? Why?
In C, a string is a sequence of character values terminated by a 0-valued character - IOW, the string "Hello" is represented as the character sequence 'H', 'e', 'l', 'l', 'o', 0. Strings are stored in arrays of char (or wchar_t for wide strings):
char str[] = "Hello";
In memory, str would look something like this:
+---+
str: |'H'| str[0]
+---+
|'e'| str[1]
+---+
|'l'| str[2]
+---+
|'l'| str[3]
+---+
|'o'| str[4]
+---+
| 0 | str[5]
+---+
It is possible to store multiple strings in a single 1D array, although almost nobody does this:
char strs[] = "foo\0bar";
In memory:
+---+
strs: |'f'| strs[0]
+---+
|'o'| strs[1]
+---+
|'o'| strs[2]
+---+
| 0 | strs[3]
+---+
|'b'| strs[4]
+---+
|'a'| strs[5]
+---+
|'r'| strs[6]
+---+
| 0 | strs[7]
+---+
The string "foo" is stored starting at strs[0], while the string "bar" is stored starting at strs[4].
Normally, to store an array of strings, you'd either use a 2D array of char:
char strs[][MAX_STR_LEN] = { "foo", "bar", "bletch" };
or a 1D array of pointers to char:
char *strs[] = { "foo", "bar", "bletch" };
In the first case, the contents of the string are stored within the strs array:
+---+---+---+---+---+---+---+
strs: |'f'|'o'|'o'| 0 | ? | ? | ? |
+---+---+---+---+---+---+---+
|'b'|'a'|'r'| 0 | ? | ? | ? |
+---+---+---+---+---+---+---+
|'b'|'l'|'e'|'t'|'c'|'h'| 0 |
+---+---+---+---+---+---+---+
In the second, each strs[i] points to a different, 1D array of char:
+---+ +---+---+---+---+
strs: | | strs[0] ------> |'f'|'o'|'o'| 0 |
+---+ +---+---+---+---+
| | strs[1] ----+
+---+ | +---+---+---+---+
| | strs[2] -+ +-> |'b'|'a'|'r'| 0 |
+---+ | +---+---+---+---+
|
| +---+---+---+---+---+---+---+
+----> |'b'|'l'|'e'|'t'|'c'|'h'| 0 |
+---+---+---+---+---+---+---+
In your code, a can (and is usually intended to) store a single string that's 9 characters long (not counting the 0 terminator). Like I said, almost nobody stores multiple strings in a single 1D array, but it is possible (in this case, a can store 2 4-character strings).
char a[10];
You've allocated 10 bytes of the stack for a. But right now, it contains garbage because you never gave it a value.
Scanf doesn't know any of this. All it does is copy bytes from the standard input into a, ignorant of its size.
And why are you doing a loop 10 times? You will overwrite a each loop iteration, so you'll only have the value from the final time.
A string is per definition a null-terminated character array. So every character array becomes a string as soon as it contains a \0 somewhere, defining the end of that string.
In memory the string is just a bunch of bytes laying (for simplicity but not necessarily) in sequence. Take the string "Hello" for example
+---+---+---+---+---+---+
| H | e | l | l | o | \0|
+---+---+---+---+---+---+
Your array char a[10] is pointing to the beginning of such a memory location ('H' in the example) with enough space to store 10 characters.
By using scanf you are storing an string (character sequence + terminating \0) in that buffer (over and over again). scanf stores the characters in there and adds a terminating \0 to the element after the last one written to. This allows you to safely store any character sequence that is at most 9 characters long, since the 10th character needs to be the \0
Does a 1D array work as a list of strings, or a single string?
quite broad question.
char a[10]; declared table a which has a size of 10 the char elements
char *a[10]; declared table a which has a size of 10 char * elements which can possible point to the string (when you allocate memory for it and copy the valid C string)
In your code:
'scanf("%s",a);' a means the address of the first element of the array. So scanf writes data there, every time overwriting the previous content. If your scanf-ed input will need more 10 elements (including trailing 0) to be stored, you will get an UB and very possible SEGFAUT
You are over-writing same buffer in loop 10 times, which means buffer will contain data entered in last reading and previous 9 strings will be lost.
Also entering more than 9 characters would cause buffer overflow which would invoke undefined behavior.
You should limit number of characters scanned from input buffer and then clear the rest of the buffer. (Not fflush(stdin);)
scanf("%9s",a);
Does a 1D array work as a list of strings, or a single string?
If its terminated with null character then yes, its string, like this. And a is the address of first element.
+---+---+---+---+---+---+----+
| S | t | r | i | n | g | \0 |
+---+---+---+---+---+---+----+
a a+1 a+2
And if you pass this array ie. to printf(), he will print all characters until he reach \0.
If you would like to read list of strings, you have to declare 2D array or pointer-to-pointer-to-char and allocate enough memory for pointers.
int c;
char a[10][10];
for(i=0;i<10;i++)
{
scanf("%9s",a[i]);
while ((c = getchar()) != '\n' && c != EOF) ;
}

Passing argument to read function, from structures like (char *) &(struct)

Reading K&R book ANSI, and bump into, source code that can't understand, it is about readdir function. That code is big. So it is like:
typedef struct {
long ino;
char name[NAME_MAX+1];
} Dirent;
and in readdir function we have:
Dirent *dirbuf;
and NOW, there is:
ignore what is this what is dis what is dis
while (read(dp->fd, (char *) &dirbuf , sizeof(dirbuf) ) == sizeof( dirbuf) )
And "what is dis and what is this" is part of the question, please explain me what it does. I had been playing with it to check if (char *) search in struct for char * and take IT to read function when find, but it doesn't? Also can you explain that statement when is checking does it equal with sizeof( dirbuf) , and why third argument isn't sizeof(dirbuf->name)? Here what i tried:
struct lele{
int dig;
char name[20];
};
int main(void)
{
struct lele p;
scanf("%d%s", (int *) &p, (char *) &p);
printf("name: %s ,,, dig : %d\n", p.name, p.dig);
return 0;
}
INPUT: 5 , green
OUTPUT: name: n ,,, dig : 1701147239
Also can explain and OUTPUT?
EDIT Mainstream question is why second argument isn't dirbuf->name ?
Code for readdir:
#include <sys/dir.h> /* local directory structure */
/* readdir: read directory entries in sequence */
Dirent *readdir(DIR *dp)
{
struct direct dirbuf; /* local directory structure */
static Dirent d; /* return: portable structure */
while (read(dp->fd, (char *) &dirbuf, sizeof(dirbuf))
== sizeof(dirbuf)) {
if (dirbuf.d_ino == 0) /* slot not in use */
continue;
d.ino = dirbuf.d_ino;
strncpy(d.name, dirbuf.d_name, DIRSIZ);
d.name[DIRSIZ] = '\0'; /* ensure termination */
return &d;
}
return NULL;
}
Back in the days of yore (or K&R), directories on a UFS (Unix File System) could be read with open(), read(), close(). Further, the file names were limited to 14 characters and inode numbers were limited to 2 bytes (unsigned short). And a directory consisted of 16-byte entries:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| inode | . | \0| \0| \0| \0| \0| \0| \0| \0| \0| \0| \0| \0| \0|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| inode | . | . | \0| \0| \0| \0| \0| \0| \0| \0| \0| \0| \0| \0|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| inode | f | i | l | e | n | a | m | e | \0| \0| \0| \0| \0| \0|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| inode | l | o | n | g | e | r | f | i | l | e | n | a | m | e |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 00000 | d | e | l | e | t | e | d | - | f | i | l | e | \0| \0|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| inode | o | t | h | e | r | n | a | m | e | \0| \0| \0| \0| \0|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
Note that 14-character names were the max, but such names were not null-terminated. Deleted entries had an inode number of zero but the name was not zapped. The null padding matches what strncpy() does (though it is not clear that strncpy() was actually used to do it).
More modern file systems allow for variable length names and avoid wasting space by only allocating as much space as necessary for the name, and they use large inode numbers.
The code shown in the question is:
while (read(dp->fd, (char *)&dirbuf, sizeof(dirbuf)) == sizeof(dirbuf))
This looks like the first edition; in those days, there was no void * and char * was the universal pointer. This executes the read() function call, treating the dirbuf variable as a buffer. sizeof(dirbuf) gives the size of the variable in bytes. So, this reads a fixed number of bytes into the variable. The read() system call returns the number of bytes it read; if that was not the number requested, there was a problem — probably EOF (indicated by zero), or perhaps -1 (problems with the file descriptor), or perhaps a number less than the size requested (indicating, probably, corruption in the file system). So, overall, the loop reads directory entries into the structure variable dirbuf.
I'm not convinced about the sizes shown in the structure (long is 4 bytes, and there was no null padding). I'd have to look at what they're up to.

2D dynamic allocation in C error when incrementing the pointer

I wanted to allocate a string array dynamically , the program is supposed to ask the user for characters and collect them in the first string in the array till letter 'q' is entered then the program starts adding the characters to the second line and so on.
When I print the characters memory location it seems like each character takes two memory cells instead of one though I increment it only once.
Here is the source code to my program
#include <stdio.h>
void main()
{
char** txt;
char* baseAddress;
txt = (char **)malloc(5*sizeof(char*));
*txt = (char *)malloc(20*sizeof(char));
baseAddress = *txt;
while (*(*txt) != 'q')
{
(*txt)++;
scanf("%c", (*txt));
printf("%p\r\n", (*txt));
}
*txt = '\0';
printf("%p", baseAddress);
free(baseAddress);
free(txt);
}
the output is like this
>j
>0x9e12021
>0x9e12022
>s
>0x9e12023
>0x9e12024
>
I think there may be something wrong with the pointers.
How do I go about accomplishing this? and sorry for the bad english
What exacty you code do :
+----------------------------------------------+
| +--------------------------------------+ |
| txt|*txt |*txt+1 |*txt+2 |*txt+3 |*txt+4 | |
| +--------------------------------------+ |
| ^ ^ no memory alloc ^ |
| | |_______not used_______| |
| +----+ |
|*txt |____| <------------------------------+---you never give a value here,
| +1 |____| <--j |
| +2 |____| <-- '\n' |
| +3 |____| <--s |
| +4 |____| <-- '\n' |
| . . |
| . . |
| . ____ |
| +19 |____| |
+----------------------------------------------+
So you need :
re-write you while loop and deal with the '\n'
when user type q , alloc new string memory and collect user input .
Suggust:
In you fisrt string
Use txt[0] instead of *txt , use txt[0][i] and i++ instead of **txt and (*txt)++ .
Hope can help. :-)
You are forgetting about the newline character.
For instance, you are probably imagining your input to be "js". However, since you are hitting the enter key, it is actually "j\ns\n".
So, you are entering two characters at a time, and it is reading two characters at a time. Your code is behaving just as it should.

Resources