In C, how can a store long strings (example passwords) - c

Well, I've got this programm checking passwords. It works fine if I set the second array (that is the for loop) to 8 digits. But as soon as the pw needs to be longer than 8 digits the whole thing goes wrong (since the for loop goes for 10 digits).
I thought declaring the first array to be MAXLINE long would work, but it doesn't seem to solve the issue.
/* IMPORT ---------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* CONST------------------ */
#define MAXDIGIT 10000
/* VARIABLES (global) ---------- */
/* MAIN--------------- */
int main()
{
/* VARIABLES (local) --------- */
/* VARIABLES (local) --------- */
// ENTERED PW:
char EnterCode[MAXDIGIT];
int i;
// REAL PW:
char arr[MAXDIGIT] = "123456789"; //"YKJ98LGDDF";
int j;
printf("PW: "); // for testing
for (j = 0 ; j < 8; ++j){
printf("%c", arr[j]);
}
/* Intro --------------------- */
printf("\nPlease enter code of authorization: ");
for(i = 0; i < 10; ++i){
scanf("%c", &EnterCode[i]);
printf("%c", EnterCode[i]); // test 1
}
if (strcmp(EnterCode,arr) == 0){
printf("\nAccess authorized.\n");
}else{
printf("\nAccess denied!\n");
}
system("PAUSE");
return 0;
}

Although you can put scanf in a loop, you do not need to do that in your application:
If the passcode is going to be captured in a string, simply declare a reasonable length string, use it to read user's input in a single call:
char EnterCode[20];//20 is just for illustration, pick any reasonable length for your application
printf("enter your passcode:\n");
scanf("%19s", EnterCode); //limit characters read to 19 (leaving room for terminating NULL)
For an exceptionally long pass-code,
rather than creating memory on the stack:
#define MAXDIGIT 10000
char EnterCode[MAXDIGIT];//uses a large block of memory from a limited source
Place it on the heap:
char *EnterCode = {0};
EnterCode = malloc(MAXDIGIT); //also uses a large block of memory, but from a much much larger source
When you are done using EnterCode, free the memory:
free(EnterCode);

In C language strings end with '\0'.
Therefore, your password should be "123456789" and after entering the "EnterCode"
set EnterCode[10] = '\0' (in your code).

Replace
for(i = 0; i < 10; ++i){
scanf("%c", &EnterCode[i]);
printf("%c", EnterCode[i]); // test 1
}
with
scanf("%s", EnterCode);
and try again.

Related

Why are there random characters outputting in my code?

I have been writing a program to input a phrase and turn it into an acronym. For some reason when I output my acronym at the moment it comes out with a bunch of random characters. How do I fix it?
#include <stdio.h>
#include <string.h>
#define MAXLEN 50
int main() {
int num;
printf("Enter number of acronyms to add to the database:");
scanf("%d", &num);
getchar();
char strings[num][MAXLEN];
char acronym[num][MAXLEN];
for(int i = 0; i < num; i++){
printf("Enter the string to convert into an acronym:");
fgets(strings[i],MAXLEN,stdin);
printf("%s\n", strings[i]);
for(int j = 0; j < 11; j++){
if((strings[i][j]) >= 'A' && (strings[i][j]) <= 'Z'){
char buffer[][20] = {strings[i][j]};
strcat(acronym[i], buffer[i]);
}
}
puts(acronym[i]);
}
return 0;
}
I have tried changing the MAXLEN value to see if it was a memory issue or like a buffer overload. I've also just tried changing around how the strings switch and work together but nothing has worked.
char buffer[][20] = {strings[i][j]};
Here you let the compiler count how many elements the array has from the initialization.
It has 1 element, A string with single a single character strings[i][j] and rest of the 20 byte array filled with 0.
strcat(acronym[i], buffer[i]);
Here you access buffer[i], but there is only one string there (as explained above), so this is invalid if i is anything but 0.
I'm not sure what you are trying to do, but this would be valid implementation of what this code tries to do:
// extract single character as a string
char buffer[2] = {strings[i][j], 0}; // only one of 2 and 0 is mandatory
// append it to acronym
strncat(acronym[i], 20, buffer);
Probably lots of other stuff there is wrong, but here is one definite issue and a possible solution.

Copying valid strings to 2d array in C

I am checking if a function returns true, it prints out valid strings according some other function I got. At the moment, it's printing it out correctly but it is also printing empty lines which seem to correspond to the invalid strings.
How can I make these empty lines go away?
Here is my code:
int main()
{
int i, count = 0;
char input[10];
char validStr[10][60] = {""};
for (i = 0; i < 60; ++i){
if(fgets(input,10, stdin) == NULL){
break;
}
input[strcspn(input,"\n")] = '\0';
if(checkIfValid(input)){
memcpy(validStr[i],input,sizeof(input));
count++;
}
}
printf("%d\n",count);
for (int j = 0 ; j < count; ++j){
printf("%s\n",validStr[j]);
}
}
The count indicates it is printing only the valid strings but as you can tell by the pic it prints white lines.
Note: For various reasons the program needs to follow the current order so the output is printed after the first for loop.
Thanks in advance!
Instead of this:
if(checkIfValid(input)){
memcpy(validStr[i],input,sizeof(input));
count++;
}
This:
if(checkIfValid(input)){
memcpy(validStr[count],input,sizeof(input));
count++;
}
As others have pointed out in the comments, you want to safely secure that string copy. May I suggest:
if(checkIfValid(input)){
char* dst = validStr[count];
size_t MAXLEN = 10;
strncpy(dst, input, MAXLEN);
dest[MAXLEN-1] = '\0';
count++;
}
Continuing from the comment, if you want to store the entire string, you need to provide adequate space for the nul-terminating character.
AAAAAAAAAA
QELETIURTE
...
contain strings that are 10 characters long and will not fit in input as declared char[10].
Instead of looping with a for, allow the return from fgets() control your read-loop and keep count as a condition controlling the loop to ensure you protect your array bounds, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 128 /* if you need a constant, #define one (or more) */
#define NSTR 10
int checkIfValid (const char *s) { return 1; (void)s; }
int main(void)
{
size_t count = 0;
char input[MAXC];
char validStr[NSTR][MAXC] = {""};
while (count < NSTR && fgets (input, sizeof input, stdin)) {
input[strcspn(input,"\n")] = '\0';
if(checkIfValid(input)){
strcpy (validStr[count], input);
count++;
}
}
printf ("%zu\n",count);
for (size_t j = 0 ; j < count; ++j) {
printf("%s\n",validStr[j]);
}
}
(adjust your array declaration for 60 strings of 10 characters each)
If you want to cut off at 9 characters and ensure the stings are nul-terminated, #selbie has that covered.
Example Use/Output
With your data (as good as I could read it) in dat/validstr.txt you could do:
$ ./bin/validstring <dat/validstr.txt
6
AAAAAAAAAA
QELETIURTE
321qweve
sdsdsdfFF
GRSGGFDDSS
toLotssAAA

How to count the number of same character in C?

I'm writing a code a that prompts the user to enter a string
&
create a function that is a type void that prints out the character that was used the most
(As in where it appeared more than any other ones)
&
also shows the number of how many times it was in that string.
Therefore here is what I have so far...
#include <stdio.h>
#include <string.h>
/* frequent character in the string along with the length of the string (use strlen from string.h – this will require you to #include <string.h> at the top of your program).*/
/* Use array syntax (e.g. array[5]) to access the elements of your array.
* Write a program that prompts a user to input a string,
* accepts the string as input, and outputs the most
* You should implement a function called mostfrequent.
* The function prototype for mostfrequent is: void mostfrequent(int *counts, char *most_freq, int *qty_most_freq, int num_counts);
* Hint: Consider the integer value of the ASCII characters and how the offsets can be translated to ints.
* Assume the user inputs only the characters a through z (all lowercase, no spaces).
*/
void mostfrequent(int *counts, char *most_freq, int *qty_most_freq, int num_counts_)
{
int array[255] = {0}; // initialize all elements to 0
int i, index;
for(i = 0; most_freq[i] != 0; i++)
{
++array[most_freq[i]];
}
// Find the letter that was used the most
qty_most_freq = array[0];
for(i = 0; most_freq[i] != 0; i++)
{
if(array[most_freq[i]] > qty_most_freq)
{
qty_most_freq = array[most_freq[i]];
counts = i;
}
num_counts_++;
}
printf("The most frequent character was: '%c' with %d occurances \n", most_freq[index], counts);
printf("%d characters were used \n", num_counts_);
}
int main()
{
char array[5];
printf("Enter a string ");
scanf("%s", array);
int count = sizeof(array);
mostfrequent(count , array, 0, 0);
return 0;
}
I'm getting the wrong output too.
output:
Enter a string hello
The most frequent character was: 'h' with 2 occurances
5 characters were used
should be
The most frequent character was: 'l' with 2 occurances
5 characters were used
let's do it short (others will correct me if I write something wrong ^_^ )
you declare a int like this:
int var;
use it like this :
var = 3;
you declare a pointer like this :
int* pvar;
and use the pointed value like this:
*pvar = 3;
if you declared a variable and need to pass a pointer to it as function parameters, use the & operator like this :
functionA(&var);
or simply save its address in a pointer var :
pvar = &var;
that's the basics. I hope it will help...
The function prototype you are supposed to use seems to include at least one superfluous parameter. (you have the total character count available in main()). In order to find the most frequently appearing character (at least the 1st of the characters that occur that number of times), all you need to provide your function is:
the character string to be evaluated;
an array sized so that each element represents on in the range of values you want to find the most frequent (for ASCII characters 128 is fine, for all in the range of unsigned char, 256 will do); and finally
a pointer to return the index in your frequency array that holds the index to the most frequently used character (or the 1st character of a set if more than one are used that same number of times).
In your function, your goal is to loop over each character in your string. In the frequency array (that you have initialized all zero), you will map each character to an element in the frequency array and increment the value at that element each time the character is encountered. For example for "hello", you would increment:
frequency['h']++;
frequency['e']++;
frequency['l']++;
frequency['l']++;
frequency['o']++;
Above you can see when you are done, the element frequency['l']; will hold the value of 2. So when you are done you just loop over all elements in frequency and find the index for the element that holds the largest value.
if (frequency[i] > frequency[most])
most = i;
(which is also why you will get the first of all characters that appear that number of times. If you change to >= you will get the last of that set of characters. Also, in your character count you ignore the 6th character, the '\n', which is fine for single-line input, but for multi-line input you need to consider how you want to handle that)
In your case, putting it altogether, you could do something similar to:
#include <stdio.h>
#include <ctype.h>
enum { CHARS = 255, MAXC = 1024 }; /* constants used below */
void mostfrequent (const char *s, int *c, int *most)
{
for (; *s; s++) /* loop over each char, fill c, set most index */
if (isalpha (*s) && ++c[(int)*s] > c[*most])
*most = *s;
}
int main (void) {
char buf[MAXC];
int c[CHARS] = {0}, n = 0, ndx;
/* read all chars into buf up to MAXC-1 chars */
while (n < MAXC-1 && (buf[n] = getchar()) != '\n' && buf[n] != EOF)
n++;
buf[n] = 0; /* nul-terminate buf */
mostfrequent (buf, c, &ndx); /* fill c with most freq, set index */
printf ("most frequent char: %c (occurs %d times, %d chars used)\n",
ndx, c[ndx], n);
}
(note: by using isalpha() in the comparison it will handle both upper/lower case characters, you can adjust as desired by simply checking upper/lower case or just converting all characters to one case or another)
Example Use/Output
$ echo "hello" | ./bin/mostfreqchar3
most frequent char: l (occurs 2 times, 5 chars used)
(note: if you use "heello", you will still receive "most frequent char: e (occurs 2 times, 6 chars used)" due to 'e' being the first of two character that are seen the same number of times)
There are many ways to handle frequency problems, but in essence they all work in the same manner. With ASCII characters, you can capture both the most frequent character and the number of times it occurs in a single array of int and an int holding the index to where the max occurs. (you don't really need the index either -- it just save looping to find it each time it is needed).
For more complex types, you will generally use a simple struct to hold the count and the object. For example if you were looking for the most frequent word, you would generally use a struct such as:
struct wfreq {
char *word;
int count;
}
Then you simply use an array of struct wfreq in the same way you are using your array of int here. Look things over and let me know if you have further questions.
Here is what I came up with. I messed up with the pointers.
void mostfrequent(int *counts, char *most_freq, int *qty_most_freq, int num_counts_)
{
*qty_most_freq = counts[0];
*most_freq = 'a';
int i;
for(i = 0; i < num_counts_; i++)
{
if(counts[i] > *qty_most_freq)
{
*qty_most_freq = counts[i];
*most_freq = 'a' + i;
}
}
}
/* char string[80]
* read in string
* int counts[26]; // histogram
* zero counts (zero the array)
* look at each character in string and update the histogram
*/
int main()
{
int i;
int num_chars = 26;
int counts[num_chars];
char string[100];
/*zero out the counts array */
for(i = 0; i < num_chars; i++)
{
counts[i] = 0;
}
printf("Enter a string ");
scanf("%s", string);
for(i = 0; i < strlen(string); i++)
{
counts[(string[i] - 'a')]++;
}
int qty_most_freq;
char most_freq;
mostfrequent(counts , &most_freq, &qty_most_freq, num_chars);
printf("The most frequent character was: '%c' with %d occurances \n", most_freq, qty_most_freq);
printf("%d characters were used \n", strlen(string));
return 0;
}

program outputs exit phrase instead of words stored in C

So I was working on an assignment for school, and had written up a variation of this code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX 100
// This program takes an input of strings and prints them out with a new line separating each one.
int main() {
char *WordArray[MAX]; //initializing variables
int i = 0;
int count = 0;
printf("enter up to 100 words, that are 20 characters maximum \n");
for (i = 0; i <100; i++){ //runs while there's less than 100 inputs
char Array[1];
scanf("%s",Array); //stores string in the array
if (strcmp(Array, "STOP") == 0) { //compares the string with stop, and if it is, it breaks out of the loop
break;
}
WordArray[i]=Array; //stores the string in the pointer array
}
printf("The output is\n");
for (count = 0; count<i; count++){ //counts up to the amount of words stored
printf("%s\n",WordArray[count]); //outputs each pointer string
}
}
and I noticed that the output was printing "STOP" instead of the values stored. Anyone have any answers to why and/or how to fix it? I know one of the methods is to switch to a 2D array instead of using pointers, but I'm still baffled as to why a program like this wouldn't work.
Your char Array[1]; isn't large enough to store any but an empty string. Also, when it works, every pointer will point to the same string, which will be the last entry you made. This makes some corrections where commented.
#include <stdio.h>
#include <stdlib.h> // instead of ctype.h
#include <string.h>
#define MAX 100
// This program takes an input of strings and prints them out with a new line separating each one.
int main() {
char *WordArray[MAX];
int i = 0;
int count = 0;
printf("enter up to 100 words, that are 20 characters maximum \n");
for (i = 0; i <100; i++){
char Array[21]; // increase size of array
scanf("%20s",Array); // limit entry length
if (strcmp(Array, "STOP") == 0) {
break;
}
WordArray[i] = strdup(Array); // allocate memory for and copy string
}
printf("The output is\n");
for (count = 0; count<i; count++){
printf("%s\n",WordArray[count]);
}
// free each string's memory
for (count = 0; count<i; count++){
free(WordArray[count]);
}
}
Program output:
enter up to 100 words, that are 20 characters maximum
one two three STOP
The output is
one
two
three
Edit: note that your code contains another undefined behaviour besides the too-short string char Array[1] which is that you dereference the pointer you stored in char *WordArray[MAX];. The scope of Array is inside the for loop, and theoretically ceases to exist after the loop completes, so the pointer you store is invalid. Here, the word entered is duplicated with strdup so that doesn't apply.

(C) How do I use dynamic memory for character input? And how do I organize the values inputed in a certain way?

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

Resources