access an argument in a string pointer char* - c

I need to try and fix sentences from an input in c, so I tried separating tokens and making new strings and then I wanted to access the first char of each string and make it a capital letter.
Now I am having trouble understanding how to access only one char of each new string, like trying to access only 'e' in hello which is in str1[0] second char.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char str1[601], * str2[601];
int i = 0, j = 0;
printf_s("*************** Welcome to the text cleaner ***************\n\n");
printf_s("Please enter text:\n");
gets_s(str1, sizeof(str1));
char* sentence=NULL,*next_sentence=NULL;
sentence = strtok_s(str1,".",&next_sentence);
while (sentence != NULL)
{
printf(" %s\n", sentence);
str2[i++] = sentence;
sentence = strtok_s(NULL, ".", &next_sentence);
}
str2[i++] = '\0';
printf_s("%s", str2[1]);
}
Code and content of variables in debugger

Here is my take on what you are trying to do. I'm showing the code and the results. I have simplified your effort since you are mixing printf and printf_s. You use the _s variant for buffer overflow control. That does not seem to be your concern while simply learning about arrays.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
char str1[601]; // This is an array of chars.
// If storing a string, final elem is 0x0
char *str2[601]; // This is a pointer to an array of chars.
//
int i = 0;
int j = 0;
// I removed your _s variants of standard libraries. Let's keep
// things simple.
printf("*************** Welcome to the text cleaner ***************\n\n");
printf("Please enter text:\n");
// ditto for gets to fgets
//
// Excerpt rom the manpage
//
// char *fgets(char *s, int size, FILE *stream);
//
// fgets() reads in at most one less than size characters from
// stream and stores them into the buffer pointed to by s.
// Reading stops after an EOF or a newline. If a newline is read,
// it is stored into the buffer. A terminating null byte ('\0')
// is stored after the last character in the buffer.
//
// fgets() returns s on success, and NULL on error or when end of
// file occurs while no characters have been read.
//str1 = fgets(str1, sizeof(str1), stdin);
// I would do a null check here.
if (NULL == fgets(str1, sizeof(str1), stdin)) {
return; // graceful exit
}
// Notice on the bracket print of your text, the closing >
// is shown on the next line. This is because its capturing the
// newline/carriage return character.
printf("You entered %d chars and the text was:\n<%s>\n", strlen(str1), str1);
// These are for your strtok operation
// I would call them tokens or words, but
// whatever.
char *sentence=NULL;
char *next_sentence=NULL;
// wants to parse a string
// Excerpt from manpage
//
// char *strtok(char *str, const char *delim);
// Ahh, now I see why you name is sentence. You
// are looking for periods to separage sentences.
printf("Lets use strtok\n");
sentence = strtok(str1, ".");
while (sentence != NULL) {
printf("A sentence is:\n %s\n", sentence);
str2[i++] = sentence;
sentence = strtok(NULL, ".");
}
// So now, your individual sentences are stored
// in the array str2.
// str2[0] is the first sentence.
// str2[1] is the next sentence.
//
// To access the characters, specify a sentence and
// then specify the character.
//
// You can do the math, but do a man ascii, look at
// difference in lowercase a and uppercase A in terms
// of ascii. If its not captializ3ed already, simply
// add that offset or error out if not in set a-z.
//
// Here I will just make the first letter of the second
// sentence to be J.
str2[1][0] = 'J';
// Note, since you are going to have in the 'space'
// since you are delimitting on '.', It will have the
// effect of replacing 'space' with 'J'.
printf("Sentence two is: \n%s\n", str2[1]);
}
Here is the code in action.
*************** Welcome to the text cleaner ***************
Please enter text:
John was here. and here.
You entered 25 chars and the text was:
<John was here. and here.
>
Lets use strtok
A sentence is:
John was here
A sentence is:
and here
A sentence is:
Sentence two is:
Jand here
I hope that helps. TLDR use str2[x][y] to access a string x at character y.

Related

How to get each string within a buffer fetched with "getline" from a file in C

I'm trying to read every string separated with commas, dots or whitespaces from every line of a text from a file (I'm just receiving alphanumeric characters with scanf for simplicity). I'm using the getline function from <stdio.h> library and it reads the line just fine. But when I try to "iterate" over the buffer that was fetched with it, it always returns the first string read from the file. Let's suppose I have a file called "entry.txt" with the following content:
test1234 test hello
another test2
And my "main.c" contains the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD 500
int main()
{
FILE *fp;
int currentLine = 1;
size_t characters, maxLine = MAX_WORD * 500;
/* Buffer can keep up to 500 words of 500 characters each */
char *word = (char *)malloc(MAX_WORD * sizeof(char)), *buffer = (char *)malloc((int)maxLine * sizeof(char));
fp = fopen("entry.txt", "r");
if (fp == NULL) {
return 1;
}
for (currentLine = 1; (characters = getline(&buffer, &maxLine, fp)) != -1; currentLine++)
{
/* This line gets "test1234" onto "word" variable, as expected */
sscanf(buffer, "%[a-zA-Z_0-9]", word);
printf("%s", word); // As expected
/* This line should get "test" string, but again it obtains "test1234" from the buffer */
sscanf(buffer, "%[a-zA-Z_0-9]", word);
printf("%s", word); // Not intended...
// Do some stuff with the "word" and "currentLine" variables...
}
return 0;
}
What happens is that I'm trying to get every alphanumeric string (namely word from now on) in sequence from the buffer, when the sscanf function just gives me the first occurrence of a word within the specified buffer string. Also, every line on the entry file can contain an unknown amount of words separated by either whitespaces, commas, dots, special characters, etc.
I'm obtaining every line from the file separately with "getline" because I need to get every word from every line and store it in other place with the "currentLine" variable, so I'll know from which line a given word would've come. Any ideas of how to do that?
fscanf has an input stream argument. A stream can change its state, so that the second call to fscanf reads a different thing. For example:
fscanf(stdin, "%s", str1); // str1 contains some string; stdin advances
fscanf(stdin, "%s", str2); // str2 contains some other sting
scanf does not have a stream argument, but it has a global stream to work with, so it works exactly like fscanf(stdin, ...).
sscanf does not have a stream argument, nor there is any global state to keep track of what was read. There is an input string. You scan it, some characters get converted, and... nothing else changes. The string remains the same string (how could it possibly be otherwise?) and no information about how far the scan has advanced is stored anywhere.
sscanf(buffer, "%s", str1); // str1 contains some string; nothing else changes
sscanf(buffer, "%s", str2); // str2 contains the same sting
So what does a poor programmer fo?
Well I lied. No information about how far the scan has advanced is stored anywhere only if you don't request it.
int nchars;
sscanf(buffer, "%s%n", str1, &nchars); // str1 contains some string;
// nchars contains number of characters consumed
sscanf(buffer+nchars, "%s", str2); // str2 contains some other string
Error handling and %s field widths omitted for brevity. You should never omit them in real code.

Concatenating Strings-changing words into pig latin

I keep receiving "Segmentation fault (core dumped)".
How can I swap the first letter of a given word that the user inputs to the end of the word and then add an "ay".
For example:
input "Code"
output "odecay"
#include<stdio.h>
#include<string.h>
int main()
{
char pig[100],p[10],i[100];
int j,length;
printf("What word would you like to change into pig latin");
scanf("%s",pig);
length=strlen(pig);
strcat(p,pig[0]);
for(j=0;j<length;j++)
{
pig[j]=pig[j+1];
}
strcat(pig,p);
strcat(pig,"ay");
printf("%s",pig);
return 0;
}
How can I swap the first letter of a given word that the user inputs to the end of the word and then add an "ay"
Save the first character ("letter")
char c = pig[0];
Move the rest of pig one char to the beginning
memmove(pig, pig + 1, strlen(pig) - 1);
alternativly use this statement
memmove(&pig[0], &pig[1], strlen(pig) - 1);
(Note that memcpy() won't work here as source and destiantion overlap.)
Replace the "old" last character with the "old", stored first character
pig[strlen(pig) - 1] = c;
Append "ay"
strcat(pig, "ay");
Print the result:
printf("%s\n", pig);
There is no need for a second "string", char-array.
Assuming pig is large enough, that is one char larger then the data to be scanned in from the user, one can even ommit the use of the intermediate character `c, as per my sketch above.
Initialise pig to all 0s
char pig[100] = "";
Scan in data
scanf("%98s", pig); /* Add tests for failure reading as needed. */
Append the first character of the input, that is copy it to the end of pig
pig[strlen(pig)] = pig[0];
Move all of pig one character to the beginning
memmove(pig, pig + 1, strlen(pig) - 1);
Print the result:
printf("%s\n", pig);
This code runs but there is a slight problem with your algorithm. Since this is probably homework I'll let you figure that part out.
#include <stdio.h>
#include <string.h>
int main()
{
// These should be initialized before use.
char pig[100] = "",
char p[10] = "";
printf("What word would you like to change into Pig Latin: ");
scanf("%s", pig);
unsigned long length = strlen(pig); // strlen returns an unsigned long
strcat(p, &pig[0]); // This needs a pointer to char
for(int j = 0; j < length; j++)
{
pig[j] = pig[j + 1];
}
strcat(pig, p);
strcat(pig, "ay");
printf("%s", pig);
return 0;
}
Input:
Code
Output:
odeCodeay
As I said, the algorithm is not quite right but now that the code runs you should be able to fix it pretty quick. Also, since you are new to programming notice some of the code formatting which makes it more readable.
EDIT
Since others have already mentioned it, changing the line strcat(p, &pig[0]); to strncat(p, pig, 1); will produce the desired output and still use your original algorithm.
strcat(p,pig[0]); // segmentation fault may happen in this line.
char *strcat(char *dest, const char *src) // takes two string but you are passing pig[0] in the second argument which is char
You can use char *strncat(char *dest, const char *src, size_t n)
Thus the proper way to concat a char to a string would be
strncat(p,&pig[0],1); // where 1 is passed in the third argument
//so that it reads only 1 char i.e. pig[0] and ignore next characters
// otherwise the whole pig string will be concatenated.

How to correctly input a string in C

I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.

How do I parse a string in C?

I am a beginner learning C; so, please go easy on me. :)
I am trying to write a very simple program that takes each word of a string into a "Hi (input)!" sentence (it assumes you type in names). Also, I am using arrays because I need to practice them.
My problem is that, some garbage gets putten into the arrays somewhere, and it messes up the program. I tried to figure out the problem but to no avail; so, it is time to ask for expert help. Where have I made mistakes?
p.s.: It also has an infinite loop somewhere, but it is probably the result of the garbage that is put into the array.
#include <stdio.h>
#define MAX 500 //Maximum Array size.
int main(int argc, const char * argv[])
{
int stringArray [MAX];
int wordArray [MAX];
int counter = 0;
int wordCounter = 0;
printf("Please type in a list of names then hit ENTER:\n");
// Fill up the stringArray with user input.
stringArray[counter] = getchar();
while (stringArray[counter] != '\n') {
stringArray[++counter] = getchar();
}
// Main function.
counter = 0;
while (stringArray[wordCounter] != '\n') {
// Puts first word into temporary wordArray.
while ((stringArray[wordCounter] != ' ') && (stringArray[wordCounter] != '\n')) {
wordArray[counter++] = stringArray[wordCounter++];
}
wordArray[counter] = '\0';
//Prints out the content of wordArray.
counter = 0;
printf("Hi ");
while (wordArray[counter] != '\0') {
putchar(wordArray[counter]);
counter++;
}
printf("!\n");
//Clears temporary wordArray for new use.
for (counter = 0; counter == MAX; counter++) {
wordArray[counter] = '\0';
}
wordCounter++;
counter = 0;
}
return 0;
}
Solved it! I needed to add to following if sentence to the end when I incremented the wordCounter. :)
if (stringArray[wordCounter] != '\n') {
wordCounter++;
}
You are using int arrays to represent strings, probably because getchar() returns in int. However, strings are better represented as char arrays, since that's what they are, in C. The fact that getchar() returns an int is certainly confusing, it's because it needs to be able to return the special value EOF, which doesn't fit in a char. Therefore it uses int, which is a "larger" type (able to represent more different values). So, it can fit all the char values, and EOF.
With char arrays, you can use C's string functions directly:
char stringArray[MAX];
if(fgets(stringArray, sizeof stringArray, stdin) != NULL)
printf("You entered %s", stringArray);
Note that fscanf() will leave the end of line character(s) in the string, so you might want to strip them out. I suggest implementing an in-place function that trims off leading and trailing whitespace, it's a good exercise as well.
for (counter = 0; counter == MAX; counter++) {
wordArray[counter] = '\0';
}
You never enter into this loop.
user1799795,
For what it's worth (now that you've solved your problem) I took the liberty of showing you how I'd do this given the restriction "use arrays", and explaining a bit about why I'd do it that way... Just beware that while I am experienced programmer I'm no C guru... I've worked with guys who absolutely blew me into the C-weeds (pun intended).
#include <stdio.h>
#include <string.h>
#define LINE_SIZE 500
#define MAX_WORDS 50
#define WORD_SIZE 20
// Main function.
int main(int argc, const char * argv[])
{
int counter = 0;
// ----------------------------------
// Read a line of input from the user (ie stdin)
// ----------------------------------
char line[LINE_SIZE];
printf("Please type in a list of names then hit ENTER:\n");
while ( fgets(line, LINE_SIZE, stdin) == NULL )
fprintf(stderr, "You must enter something. Pretty please!");
// A note on that LINE_SIZE parameter to the fgets function:
// wherever possible it's a good idea to use the version of the standard
// library function that allows you specificy the maximum length of the
// string (or indeed any array) because that dramatically reduces the
// incedence "string overruns", which are a major source of bugs in c
// programmes.
// Also note that fgets includes the end-of-line character/sequence in
// the returned string, so you have to ensure there's room for it in the
// destination string, and remember to handle it in your string processing.
// -------------------------
// split the line into words
// -------------------------
// the current word
char word[WORD_SIZE];
int wordLength = 0;
// the list of words
char words[MAX_WORDS][WORD_SIZE]; // an array of upto 50 words of
// upto 20 characters each
int wordCount = 0; // the number of words in the array.
// The below loop syntax is a bit cyptic.
// The "char *c=line;" initialises the char-pointer "c" to the start of "line".
// The " *c;" is ultra-shorthand for: "is the-char-at-c not equal to zero".
// All strings in c end with a "null terminator" character, which has the
// integer value of zero, and is commonly expressed as '\0', 0, or NULL
// (a #defined macro). In the C language any integer may be evaluated as a
// boolean (true|false) expression, where 0 is false, and (pretty obviously)
// everything-else is true. So: If the character at the address-c is not
// zero (the null terminator) then go-round the loop again. Capiche?
// The "++c" moves the char-pointer to the next character in the line. I use
// the pre-increment "++c" in preference to the more common post-increment
// "c++" because it's a smidge more efficient.
//
// Note that this syntax is commonly used by "low level programmers" to loop
// through strings. There is an alternative which is less cryptic and is
// therefore preferred by most programmers, even though it's not quite as
// efficient. In this case the loop would be:
// int lineLength = strlen(line);
// for ( int i=0; i<lineLength; ++i)
// and then to get the current character
// char ch = line[i];
// We get the length of the line once, because the strlen function has to
// loop through the characters in the array looking for the null-terminator
// character at its end (guess what it's implementation looks like ;-)...
// which is inherently an "expensive" operation (totally dependant on the
// length of the string) so we atleast avoid repeating this operation.
//
// I know I might sound like I'm banging on about not-very-much but once you
// start dealing with "real word" magnitude datasets then such habits,
// formed early on, pay huge dividends in the ability to write performant
// code the first time round. Premature optimisation is evil, but my code
// doesn't hardly ever NEED optimising, because it was "fairly efficient"
// to start with. Yeah?
for ( char *c=line; *c; ++c ) { // foreach char in line.
char ch = *c; // "ch" is the character value-at the-char-pointer "c".
if ( ch==' ' // if this char is a space,
|| ch=='\n' // or we've reached the EOL char
) {
// 1. add the word to the end of the words list.
// note that we copy only wordLength characters, instead of
// relying on a null-terminator (which doesn't exist), as we
// would do if we called the more usual strcpy function instead.
strncpy(words[wordCount++], word, wordLength);
// 2. and "clear" the word buffer.
wordLength=0;
} else if (wordLength==WORD_SIZE-1) { // this word is too long
// so split this word into two words.
strncpy(words[wordCount++], word, wordLength);
wordLength=0;
word[wordLength++] = ch;
} else {
// otherwise: append this character to the end of the word.
word[wordLength++] = ch;
}
}
// -------------------------
// print out the words
// -------------------------
for ( int w=0; w<wordCount; ++w ) {
printf("Hi %s!\n", words[w]);
}
return 0;
}
In the real world one can't make such restrictive assumptions about the maximum-length of words, or how many there will be, and if such restrictions are given they're almost allways arbitrary and therefore proven wrong all too soon... so straight-off-the-bat for this problem, I'd be inclined to use a linked-list instead of the "words" array... wait till you get to "dynamic data structures"... You'll love em ;-)
Cheers. Keith.
PS: You're going pretty well... My advise is "just keep on truckin"... this gets a LOT easier with practice.

Ignore first word from the line in c

I am working on a code and need some help.
There is a line which needs to be read from a file. The first word must be ignored and the remaining characters (white spaces included) have to be stored into variable. How do I do it?
This will work if your word has no spaces in front of it and you use white space (' ') as separating character.
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[80];
char storage[80];
fgets(buffer, 80, stdin); // enter: »hello nice world!\n«
char *rest = strchr(buffer, ' '); // rest becomes » nice world!\n«
printf("rest: »%s«\n", rest); // » nice world!\n«
printf("buffer: »%s«\n", buffer); // »hello nice world!\n«
strncpy( storage, rest, 80 ); // storage contains now » nice world!\n«
printf("storage: »%s«\n", storage); // » nice world!\n«
// if you'd like the separating character after the "word" to be any white space
char *rest2 = buffer;
rest2 += strcspn( buffer, " \t\r\n" ); // rest2 points now too to » nice world!\n«
printf("rest2: »%s«\n", rest2); // » nice world!\n«
return 0;
}
Some examples. Read the comments in the program to understand the effect. This will assume that words are delimited by whitespace characters (as defined by isspace()). Depending on your definition of "word", the solution may differ.
#include <stdio.h>
int main() {
char rest[1000];
// Remove first word and consume all space (ASCII = 32) characters
// after the first word
// This will work well even when the line contains only 1 word.
// rest[] contains only characters from the same line as the first word.
scanf("%*s%*[ ]");
fgets(rest, sizeof(rest), stdin);
printf("%s", rest);
// Remove first word and remove all whitespace characters as
// defined by isspace()
// The content of rest will be read from next line if the current line
// only has one word.
scanf("%*s ");
fgets(rest, sizeof(rest), stdin);
printf("%s", rest);
// Remove first word and leave spaces after the word intact.
scanf("%*s");
fgets(rest, sizeof(rest), stdin);
printf("%s", rest);
return 0;
}

Resources