I want to write a program in C that fills an array p[MAX][N] of strings
I used this but i dont know which is the null string to enter when i give input.
#include <stdio.h>
#include <string.h>
#define R 3
#define C 8
int main()
{
int i;
char strings[R][C];
printf("***Table of Strings - Names***\n\n");
for(i=0;(i<R && gets(strings[i]));i++)
;
if(i==R)
printf("\n**Table Full - input terminated \n");
for(i=0;i<R;i++)
puts(strings[i]);
return 0;
}
First, never use gets(). It is inherently dangerous as it doesn't do any bounds checking on the memory you pass to it. Use fgets() instead:
for (i = 0; i < R && fgets(strings[i], C, stdin); ++i);
Note that fgets() will leave any new line ('\n') in the input at the end of the string, assuming that the whole line can fit in your buffer. If the whole line can't fit in your buffer, then it reads as much as can fit into your buffer (leaving room for and always appending a nul terminator), stops reading the input at that point and leaves the rest of the input on the stream. With C being so small in your program, such an occurrence is quite likely.
Alternatively, you could use getline() if it's available on your platform:
char *strings[R] = { 0 };
size_t cap;
for (i = 0; i < R && 0 <= getline(&strings[i], (cap = 0, &cap), stdin));
if (i == R)
printf("\n**Table Full - input terminated \n");
for (i = 0; i < R && strings[i]; ++i)
puts(strings[i]);
/* program done; clean up strings */
for (i = 0; i < R && strings[R]; ++i)
free(strings[R]);
getline() automatically dynamically (re)allocates the memory necessary to fit the next line from the input stream. It also leaves any new line ('\n') in the input at the end of the string.
Second, ctrl-D is typically used terminate the input to a program from a terminal.
It worked. I changed it to this
int main()
{
int i,j,max,thesi,sum=0,countCH=0,mikos=0;
char strings[R][C];
printf("***Table of Strings - Names***\n\n");
for(i=0;(i<R && fgets(strings[i],C,stdin ));i++)
;
if(i==R)
printf("\n**Table Full - input terminated \n");
for(i=0;i<R;i++)
fputs(strings[i],stdout);
//Euresh megistou string
max=0;
sum=0;
for(i=0;i<R;i++)
{
mikos=strlen(strings[i])-1;
sum+=mikos;
if(mikos>max)
{
max=mikos;
thesi=i;
}
}
printf("\nTo string me to megalitero mikos einai auto pou brisketai sthn %d seira \nkai einai to %s \nme mhkos %d",thesi+1,strings[thesi],max);
printf("\nO pinakas me ta strings periexei %d xaraktires\n",sum);
return 0;
}
It works just fine only that strlen counts all the chars of the string including null char why is that i dont get it?
Related
int main() {
char userInput[100]; //Store user input
//Take user input
//scanf(" %s",&userInput);
//scanf("%[^\n]s",&userInput);
//scanf("%[^\n]", &userInput);
//gets(userInput);
scanf("%[]s", &userInput); //This takes input but doesnt leave input loop
printf(" %s",userInput);
//i = index to start for looping through the string, starting at the beginning
//count = Stores occurrences of '$'
//inputLength = length of the input, used for limit of loop
int i =0,count =0;
int inputLength = strlen(userInput);
//Loop through the user input, if the character is '$', the integer count will be incremented
for (i; i < inputLength; i++){
if (userInput[i] == '$'){
count++;
}
}
printf("%d", count);
return 0;
}
Hi i'm having some issues with my code, i need to take an input of 3 lines and count the number of'$' in the input. The input method not commented "scanf("%[]s", &userInput);" is the one only i have discovered to take all 3 lines of input, BUT i can't break the input loop and continue with my program.
Any help would be greatly appreciateed
To read 3 lines with the cumbersome scanf(), code needs to look for '$', '\n', and EOF. The rest of input is discardable.
int count = 0;
int line = 0;
while (line < 3) {
scanf("%*[^$\n]"); // Scan for any amount of characters that are not $ nor \n,
// "*" implies - do not save.
char ch;
if (scanf("%c", &ch) != 1) { // Read next character.
break;
}
if (ch == '$') count++;
else line++;
}
printf("$ count %d\n", count);
As #chux suggested, reading with fgets provides a convenient way to protect from buffer overrun and without having to hard code field-width modifiers in scanf conversion specifiers.
Here, if all you need to do is count the number of '$' characters found in your input (regardless of how many lines), you can simply read ALL the input in fixed sized chunks of data. fgets does just that. It doesn't matter if you have one line, or one million lines of input. It also doesn't matter if your input lines are one-character or one million characters long. You can simply read each line and count the number of '$' found within each chunks of data read, keeping a count of the total found.
You can do this for any character. If you wanted to also count the number of line, you can simply check for '\n' characters and keep a total there as well. The only corner-case in counting lines with fgets is to insure you protect against a non-POSIX end-of-file (meaning a file with no '\n' as the final character). There are a couple of ways to handle this. Checking that the last character read was a '\n' is as good as any.
Putting the pieces together, and protecting against a non-POSIX eof, you could do something similar to the following, which simply reads all data available on stdin and outputs a final '$' and line count:
#include <stdio.h>
#define MAXC 100
int main (void) {
char buf[MAXC] = ""; /* buffer to hold input in up to MAXC size chunks */
size_t lines = 0, dollars = 0; /* counters for lines and dollar chars */
int i = 0;
while (fgets (buf, MAXC, stdin)) /* read all data */
for (i = 0; buf[i]; i++) /* check each char in buf */
if (buf[i] == '$') /* if '$' found */
dollars++; /* increment dollars count */
else if (buf[i] == '\n') /* if '\n' found */
lines++; /* increment line count */
if (i && buf[i-1] != '\n') /* protect against non-POSIX eof */
lines++;
/* output results */
printf ("input contained %zu lines and %zu '$' characters.\n",
lines, dollars);
return 0;
}
Look things over and let me know if you have further questions.
scanf("%[]s", &userInput);" is the one only i have discovered to take all 3 lines of input, BUT i can't break the input loop and continue with my program.
"%[]" is an invalid scanf() specifier. Anything may happen, it is undefined behavior, including taking all lines in and not returning.
The 's' in the format serves no purpose here - drop it.
Yes fgets() is best but let us abuse scanf() to read 3 lines and look for '$'.
char line[3][100] = {0};
// v--------- Consume all leading whitespace
// | vv ----- limit input to 99 characters as scan() appends a \0
// | || v-v-- Look for "not \n"
#define FMT_1LINE " %99[^\n]"
// Let the compiler concatenate the 3 formats into 1 string for scanf
int scan_count = scanf(FMT_1LINE FMT_1LINE FMT_1LINE, line[0], line[1], line[2]);
// Check return value
if (scan_count == 3) {
// Successfully read 3 lines
int count = 0;
for (int line_index = 0; line_index < 3; line_index++) {
char *s = line[line_index];
while (*s) { // no need for strlen(), just loop until the null character
count += *s == '$';
s++;
}
}
printf("$ count %d\n", count);
}
You write:
scanf("%[]s", &userInput); //This takes input but doesnt leave input loop
but the comment is at best misleading. Your format string is malformed, so the behavior of the scanf call is undefined. An empty scan set (between the [] in the format) does not make sense, because the resulting field could never match anything. Therefore, a ] appearing immediately after the opening ] of the scan set is interpreted as a literal character not the ending delimiter. Your scan set is therefore unterminated.
Note, too, that %[ is its own field type, separate from %s. An 's' following the closing ] of the scan set is not part of such a field descriptor, but rather an ordinary character to match.
A trivial way to do this with scanf would be to read characters one at a time in a loop via a %c field. This is probably not what the exercise is looking for, and it's a hack to use scanf() instead of getchar() for this purpose, but perhaps it would serve:
int nl_count = 0;
int dollar_count = 0;
do {
char c;
int result = scanf("%c", &c);
if (result != 1) {
break;
}
switch (c) {
case '\n':
nl_count++;
break;
case '$':
dollar_count++;
break;
}
} while (nl_count < 3);
I'm afraid it would be much more complicated to do it safely reading multiple characters at a time with a %[ field, and there is no safe way to read all three lines in one scanf call, unless you can rely on the input lines not to exceed a line length limit known to you.
int readMatrix() {
char userInput[100][3]; //Store user input
int j = 0, m = 0;
for(m = 0; m < 3; m++){
scanf("%s", &userInput[j][m]); //This takes input (Ex: 22 *(enter)* 33$ *(enter)* 66$ *(enter)*
j++; //increase the column
}
int i =0,count =0;
m = 0;
//Loop through the user input, if the character is '$', the integer count will be incremented
for (i = 0; i < 100; i++){
for(m = 0; m < 3; m++){
if (userInput[i][m] == '$'){
count++;
}
}
}
printf("%d", count);
return 0;
}
I am trying to compare strings in a mergesort algorithm after reading characters from a file as integers, and converting them to strings in an array. I am able to get the strings to print out, but when the char[] array is passed to the mergesort algorithm, the program crashes at the strcmp() step which is in the merge() step of the merge sort.
I tested to see that my temp char[] arrays are not initializing properly, so I think the problem is that I am not passing the original char[] array "charr" to the mergsort function.
I am lost as to how to do this. I borrowed the mergesort algorithm from the web, and it works on int arrays, but the simple change of changing int[] arrays to char[] arrays does not work.
How is it possible to get the char[] array that I want the sort done on to pass properly and initialize in the mergesort function?
The permutations look like this in the text file:
aaaab
aaaba
aabaa
abaaa
baaaa
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void) {
int arr[243][6];
//This is the array that I want to store my strings
char *charr[243][6];
int c, i = 0 , j = 0;
FILE *file;
file = fopen("permutations.txt", "r");
if (file) {
while ((c = getc(file)) != EOF) {
// we are reading each char in the string
//every time we hit a new line char (\n = 10)
//advance the array one, otherwise add the
// char
if (c != 10) {
arr[i][j] = c;
j++;
}
else {
arr[i][j] = c;
sprintf(charr[i], "%d%d%d%d%d%d", arr[i][0], arr[i][1],
arr[i][2], arr[i][3], arr[i][4]);
i++;
j = 0;
}
}
fclose(file);
}
if (strcmp(charr[0],charr[1]) < 0)
printf("less\n");
else
printf("other\n");
r_mergesort(charr,0,242);
for (int k = 0; k < 243; k++) {
printf(charr[k]);
for (int l = 0; l < 6; l++) {
putchar(arr[k][l]);
}
}
return 0;
}
/*l is for left index and r is right index of the sub-array*/
void r_mergesort (char arr[], int l, int r) {
//base case
if (l < r) {
//divide
int m = (l + r) /2;
// recursively sort halves
r_mergesort(arr, l, m);
r_mergesort(arr, m + 1, r);
// merge results
merge(arr, l, m, r);
}
}
void merge (char arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// create temp arrays
char left[n1], right[n2];
// copy data to temp arrays
for (i = 0; i < n1; i++) {
left[i] = arr[l + i];
}
for (j = 0; j < n2; j++)
right[j] = arr[m + 1 + j];
// merge the temp arrays back into arr[]
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (strcmp(left[i], right[j]) < 0) {
arr[k] = left[i];
i++;
}
else {
arr[k] = right[j];
j++;
}
k++;
}
//copy the remaining elements of left[]
while (i < n1) {
arr[k] = left[i];
i++;
k++;
}
//copy the remaining elements of right[]
while (i < n2) {
arr[k] = right[j];
j++;
k++;
}
}
While there is nothing wrong with character-oriented input (e.g. getc) if, as you describe, your permutations.txt contains one possible permutation per-line, then using line-oriented input will simplify your read (which I suspect is where a bulk of your problem lies). So let's get you reading your data file properly as a start to solving your issues.
Using line-oriented input, your primary functions are fgets and getline. Each has certain pluses and minuses. Since you are dealing exclusively with static declarations, we will use fgets below for the example.
One thing to be aware of with line-oriented input, is that fgets will read until a newline ('\n') is encounter or the maximum number of characters specified (minus 1 leaving room for the nul-terminator). What this means in your case is, if you have declared charr[243][7] and have 6 chars per-line (plus the '\n' for a total of 7 chars) you will run into problems if you do not increase your string size by an additional character to allow the '\n' to be read as part of each line (and also providing space for the nul-terminator).
Basically what will happen is you will tell fgets to read a max of 7 chars which means it will read all 6 of your permutation characters, but leave the '\n' at the end of the line unread. Your next call to fgets will read only the '\n'. To solve the entire problem, simply declare charr[243][8] = {{0}}; to allow a complete read of each line.
You may say, 'that doesn't sound much simpler' -- it is, I just wanted to make sure and give a thorough explanation so you don't end up caught in a subtle issue of reading 1-less that the whole line. Of course, since all line-oriented input functions, read and include the '\n' as part of their read, you will want to remove the newline from the stings stored in the array. After the explanation, hopefully the example will make the read much clearer:
#include <stdio.h>
#include <string.h>
#define MAXR 243
#define MAXC 8
int main (int argc, char **argv) {
char charr[MAXR][MAXC] = {{0}};
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
size_t i = 0;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}
while (i < MAXR && fgets (charr[i], MAXC, fp))
{
/* get length, strip trailing newline */
size_t len = strlen (charr[i]);
if (charr[i][len-1] == '\n') charr[i][len-1] = 0;
printf (" charr[%zu] : %s\n", i, charr[i]);
i++;
}
if (fp != stdin) fclose (fp);
return 0;
}
The code above simply reads and prints (with the line index) each permutation read from the file given as the first argument to the program (or from stdin if no filename is given). It is just to confirm the read of your permutations.txt file to begin with.
Compile
gcc -Wall -Wextra -O3 -o bin/readperm readperm.c
Test Input (permutations.txt)
$ cat permutations.txt
123456
234561
345612
456123
Output
$ ./bin/readperm permutations.txt
charr[0] : 123456
charr[1] : 234561
charr[2] : 345612
charr[3] : 456123
While fgets and getline are the primary tools for line-oriented input, and I rarely recommend the scanf family of functions, if your permutations.txt file is exactly as you describe fscanf can be used very efficiently in this case. Generally, the choice of format-string and proper format-specifiers is what gives new C programmers fits. Since fscanf doesn't require that you read the newline, you can use the char charr[243][7] = {{0}}; declaration and not have to worry about removing the included newline. Specifically, you can replace the read loop above with:
while (i < MAXR && fscanf (fp, " %[^\n]%*c", charr[i]) == 1)
{
printf (" charr[%zu] : %s\n", i, charr[i]);
i++;
}
Note the choice of format specifier " %[^\n]%*c". The leading space between the opening " and '%' will skip any whitespace before the first character. The character case expression used as a format-specifier %[^\n] will read all characters up to, but not inlcuding, the newline. The assignment-suppression %*c will read and discard the '\n' without including it in your string (or in the match-count returned by fscanf).
note you could simply use a " %s" format specifier and accomplish the same read in your case, but that would have eliminated the explanation of the various parts of the format-string that is critical to understanding correct use of the scanf family of functions.
Lastly, note above the use of the return == 1. fscanf returns the number of successful conversions (according to the format-specifiers). Therefore you want to continue your read so long as fscanf makes a single conversion to string each time it is called. When it fails to make a proper conversion your read loop terminates (you can assign the return to a variable and check within the body of the loop to confirm EOF versus a read error)
Let me know when you get your read of permutations.txt sorted out and we will work on any lingering issues you have after confirming you have your read fixed.
try char *charr[243][6]; --> char charr[243][7];
char arr[] --> char arr[][7] The modified program you consider it
sprintf(charr[i], "%d%d%d%d%d%d" --> sprintf(charr[i], "%c%c%c%c%c%c"
– BLUEPIXY
The three changes you suggested were the ones that got me on the right track. I had to initialize then entire length of each string in the merge algorithm, it was not enough to say left[i] = arr[l + i].
– lefunction
Hi I am still new to c and have been working on this word sort program for some time now. the guidelines are:
Write a program that sorts a series of words entered by the user. Assume that each word is no more than 20 characters long. Stop reading when the user enters an empty word. Store each word in a dynamically allocated string, using an array of pointers (use the read_line function). After all lines have been read sort the array. Then use a loop to print the words in sorted order.
The problem I seem to be having is that the program will accept words but when I enter the empty word it goes to a new line and nothing happens. An help or advice would be greatly appreciated. here is my code so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20
#define LIM 20
int read_line(char str[], int n);
void sort_str(char *list[], int n);
int alpha_first(char *list[], int min_sub, int max_sub);
int main(void)
{
char *list[LIM];
char *alpha[LIM];
char word_str[LEN];
int word, i, j, num_count = 0;
for(;;){
printf("Enter a word: ");
scanf("%s", &word);
if(word == NULL)
break;
else
read_line(word_str, LEN);
list[i] = malloc(strlen(word_str) + 1);
strcpy(list[i], word_str);
alpha[i] = list[i];
}
sort_str(alpha, i);
for(i = 0; i < num_count; ++i){
printf("Sorted: ");
puts(list[i]);
}
return (0);
}
int read_line(char str[], int n)
{
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
str[i++] = ch;
str[i] = '\0';
return i;
}
void sort_str(char *list[], int n)
{
int i, index_of_min;
char *temp;
for (i= 0; i < n - 1; ++i) {
index_of_min = alpha_first(list, i, n - 1);
if (index_of_min != i) {
temp = list[index_of_min];
list[index_of_min] = list[i];
list[i] = temp;
}
}
}
int alpha_first(char *list[], int min_sub, int max_sub){
int i, first;
first = min_sub;
for(i = min_sub + 1; i <= max_sub; ++i){
if(strcmp(list[i], list[first]) < 0){
first = i;
}
}
return (first);
}
Your logic flow is flawed. If a word is entered, the scanf() will eat it from stdin and store a null-terminated string at the address of the integer 'word'. Any more than 3/7 chars entered, (32/64 bit, allowing for the null terminator), will start corrupting the stack. read_line() will then only have the line terminator to read from stdin, (assuming the UB doesn't blow it up first).
The problem I seem to be having is that the program will accept words but when I enter the empty word it goes to a new line and nothing happens.
There are several problems with this:
char word_str[LEN];
int word, i, j, num_count = 0;
/* ... */
scanf("%s", &word);
if(word == NULL)
break;
First, scanf("%s", &word) scans whitespace-delimited strings, and to that end it skips leading whitespace, including newlines. You cannot read an "empty word" that way, though you can fail to read a word at all if the end of the input is reached (or an I/O error occurs) before any non-whitespace characters are scanned.
Second, you are passing an inappropriate pointer to scanf(). You should pass a pointer to a character array, but you instead pass a pointer to an int. It looks like maybe you wanted to scan into word_str instead of into word.
Third, your scanf() format does not protect against buffer overflow. You should provide a field width to limit how many characters can be scanned. Moreover, you need to be sure to leave room for a string terminator.
Fourth, you do not check the return value of scanf(). If it fails to match any characters to the field, then it will not store any. Since it returns the number of fields that were successfully scanned (or an error indicator), you can detect this condition.
One way to correct the scanf() and "empty word" test would be:
int result;
result = scanf("%*[ \t]%19[^ \t\n]", word_str);
if (result < 1) break;
(That assumes a fixed maximum word length of 19 to go with your declared array length of 20.) You have several additional problems in your larger code, large among them that read_line() attempts to read the same data you just read via scanf() (in fact, that function looks altogether pointless). Also, you never update num_count, and after calling sort_str() you lose track of the number of strings you've read by assigning a new value to variable i.
There may be other problems, too.
These are the directions:
Read characters from standard input until EOF (the end-of-file mark) is read. Do not prompt the user to enter text - just read data as soon as the program starts.
Keep a running count of each different character encountered in the input, and keep count of the total number of characters input (excluding EOF).
I know I have to store the values in an array somehow using the malloc() function. I have to organize each character entered by keeping count of how many times that particular character was entered.
Thanks for the help!
Actually, since you are reading from standard input, there are at most 256 different possibilities. (You read in a char). Since that's the case, you could just statically allocate 256 integers for counting. int charCount[256]; Just initialize each value to 0, then increment each time a match is input.
Alternatively, if you must have malloc, then:
// This code isn't exactly what I'd turn in for homework - just a starting
// point, and non-tested besides.
int* charCount = (int*) malloc(sizeof(int) * 256); // Allocate 256.
for (int i = 0; i < 256; i++) charCount[i] = 0; // Initialize to 0.
// Counting and character input go here, in a loop.
int inputChar;
// Read in inputChar with a call to getChar(). Then:
charCount[inputChar]++; // Increment user's input value.
// Provide your output.
free(charCount); // Release your memory.
Here is a possible solution:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int count[256] = {0};
char *l, *lp;
while (scanf(" %ms", &l) != EOF) {
for (lp = l; *lp; lp++)
count[(int)*lp]++;
free(l);
}
for (int i = 0; i < 256; i++) {
if (isprint(i) && count[i])
printf("%c: %d\n", i, count[i]);
}
exit(EXIT_SUCCESS);
}
Compile:
c99 t.c
Run:
$ ./a.out
abc
ijk
abc
<-- Ctrl-D (Unix-like) or Ctrl-Z (Windows) for EOF
a: 2
b: 2
c: 2
i: 1
j: 1
k: 1
I'm kind of new to C, and the input reading is really confusing me. I'm trying to initialize an array of size 4, but sometimes the user will enter valid input of 3. In Java, I could check the length of the input and add conditionals, but I'm not sure how this works in C.
main(void){
char str[N];
int i;
for(i = 0; i < N; i++){
scanf("%c", &str[i]);
}
for(i = 0; i < N; i++){
printf("%c\n", str[i]);
}
}
Right now, if I input 4 or more, it works fine. If I input 3, it breaks. I'd like it to handle both 3 or 4 characters.
Actually, the root of the problem is: I'm trying to figure out a way in C to read in a 24-hour-clock time, and add it to a 24-hour-clock duration. Should I be approaching this an entirely different way?
Thanks,
The short answer is: you can't.
Using scanf() is particularly dangerous because of this if you want to read in a string (%s); if the user enters more input than your buffer can hold, you have a buffer overflow on your hands.
fgets() on the other hand, allows you to specify the max number of bytes you will read, preventing you from overflowing the buffer.
Here's a quick example on how you'd write a function for some input that verified that the input was within a specified length and was a complete line (ending with \n - this routine discards the \n from the input):
void getInput(char *question, char *inputBuffer, int bufferLength)
{
printf("%s (Max %d characters)\n", question, bufferLength - 1);
fgets(inputBuffer, bufferLength, stdin);
if (inputBuffer[strlen(inputBuffer) -1] != '\n')
{
int dropped = 0;
while (fgetc(stdin) != '\n')
dropped++;
if (dropped > 0) // if they input exactly (bufferLength - 1)
// characters, there's only the \n to chop off
{
printf("Woah there partner, your input was over the limit by %d characters, try again!\n", dropped );
getInput(question, inputBuffer, bufferLength);
}
}
else
{
inputBuffer[strlen(inputBuffer) -1] = '\0';
}
}
int main()
{
char firstAnswer[10];
getInput("Go ahead and enter some stuff:", firstAnswer, 10);
printf("Okay, I got: %s\n",firstAnswer);
}
scanf() allows the use of maximum width specifiers:
So scanf("%3s", buffer) reads at most 3 characters + 1 NUL terminator.