My intention was to use the command line to read input and store it into an array and modify the characters of the array. If the character is '1', then turn it into '0', vice versa. I successfully store the input into an array, yet failed to modify the characters of the array. If I put 0000000000000000000000000000000(32bits) into my program, the output doesn't change.
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *a = argv[argc-1];
char arr[33];
size_t length = strlen(a);
for(size_t i=0;i<length;i++) {
arr[i]=a[i];
}
for(int j=0; j<32;j++) {
if(arr[j]=='0') {
arr[j]='1';
}
if(arr[j]=='1') {
arr[j]='0';
}
}
for(int k=0;k<32;k++) {
printf("%c",arr[k]);
}
}
If I put 0000000000000000000000000000000(32bits) into my program, the output doesn't change.
First of all, your program is not processing bits of input but it is processing the characters of input you are passing as command line argument to your program. If you want to process the bits of input, to start with, read about bitwise operators first.
Look at this for loop:
for(int j=0; j<32;j++) {
if(arr[j]=='0') {
arr[j]='1';
}
if(arr[j]=='1') {
arr[j]='0';
}
}
If current processing arr element value is '0', the second if condition in the for loop body will nullify the effect of first if condition on that arr element i.e. the arr element value will be unchanged and if the current processing arr element value is '1' than it will be set to '0'. So, after the loop, all the elements of array arr, which have original value as either '1' or '0', will set to '0' and that's the flaw in your logic.
Few suggestions:
If program is supposed to receive command line argument('s), make sure to put check on argc value. In your case, user is supposed to pass the string comprised of '0's and '1's, so you should check on argc value, something like:
if (argc != 2) {
printf ("Usage: <exe_name> <string_of_0s_and_1s>\n");
return 1;
}
Since, you do not have check on argc value in your program, if user do not pass any string from command line, the value of argc may be 1 and ,in this case, argv[argc-1] (or argv[0]) represents the program name or if the program name is not available from the host environment than argv[0][0] will be the null character. If argv[0] represents program name whose length is greater than 32 characters then your program will land up in undefined behaviour territory because there is no check on whether the command line input string length is <= 32 characters while copying it to arr buffer.
Since you are copying the input to char array (not as string) declare arr as array of 32 characters and not 33 characters. Looks like, you have assumed the input will be of size <= 32 characters. There is no problem with this assumption as long as program is running in a controlled environment where you are taking care of it. But still, by chance, if input string length is > 32 characters then your program behaviour will be undefined as it will end up processing array arr beyond it's size. You should add a check on length of input string as well:
if (length > 32) {
printf ("Input string length is >= 33 character.\n" \
"The permitted input string length is <= 32 characters.\nExiting..\n");
return 1;
}
If you want the input string to be of exact 32 characters, you can add check if (length != 32).
While copying the string, you can also add check on the characters of input string and if it contain character other than '1' and '0' then throw error message and exit.
Putting these altogether :
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
char *a = NULL;
char arr[32];
if (argc != 2) {
printf ("Usage: <exe_name> <string_of_0s_and_1s>\n");
return 1;
}
a = argv[argc-1];
size_t length = strlen(a);
if (length > 32) {
printf ("Input string length is > 32 characters.\n" \
"The permitted input string length is <= 32 characters.\nExiting..\n");
return 1;
}
for (size_t i = 0; i < length; i++) {
if ((a[i] != '1') && (a[i] != '0')) {
printf ("Found a character other than characters '1' and '0' in the input string.\n" \
"The input string should comprised of characters `1' and '0' only.\nExiting..");
return 1;
}
arr[i] = a[i];
}
for (size_t j = 0; j < length; j++) {
if (arr[j] == '0') {
arr[j] = '1';
} else {
arr[j] = '0';
}
}
for (size_t k = 0; k < length; k++) {
printf ("%c", arr[k]);
}
return 0;
}
you forget to give an else if condition in this part of the code.
for(int j=0; j<32;j++) {
if(arr[j]=='0') {
arr[j]='1';
}
else if(arr[j]=='1') { //This part should be else if
arr[j]='0';
}
}
In your code for the value of 0 it changed to 1. But for another if condition the value changed to 0 again.
To copy string you need to copy null character as well.
size_t length = strlen(a);
14 for(size_t i=0;i<=length;i++){
15 arr[i]=a[i];
But you do not need to traverse the string twice
size_t i=0;
while((arr[i]=a[i])) i++;
Your if is wrong. It should be
if(arr[j]=='0') arr[j]='1';
else arr[j]='0';
I'm writing a code in C to find the digits that repeat in a given number, and the one that I wrote works fine for small numbers, but the output gets messed up if I input a large value, N < 1000.
Here is my code; please help me out!
For the input:
1839138012980192380192381090981839
I get this output:
0 2 3 5 7 8
#include <stdio.h>
int main()
{
int digit, digits[10], flag = 0, i;
long long num;
scanf("%lld", &num);
while (num)
{
digit = num % 10;
if (digits[digit])
flag = 1;
digits[digit]++;
num /= 10;
}
if (flag)
{
for (i = 0; i < 10; i++)
{
if (digits[i] > 1)
printf("%d ", i);
}
printf("\n");
}
else
printf("The are no repeated digits.\n");
return 0;
}
The long long type can only represent a limited range of numbers. In your C implementation, 1839138012980192380192381090981839 is too big for long long, and scanf("%lld", &num) does not work.
Instead, read each character of input using c = getchar();, where c is declared as an int. If, after getchar, c is EOF, stop looping and print the results. If c is not EOF, then check whether it is a digit using if (isdigit((unsigned char) c)). The isdigit function is defined in <ctype.h>, so include that header.
If the character is a digit, then convert it from a character to the number it represents using c - '0'. You can use int d = c - '0'; to store the number in d. Then increment the count for the digit d.
If the character is not a digit, you can decide what to do:
There will likely be a new-line character, '\n', at the end of the line the user entered. You may want to ignore it. When you see the new-line, you could end the loop and print the results, you could continue reading to see if there are any other digits or characters before EOF is seen and report a problem to the user if there are, or you could ignore it and continue looping.
There could be spaces in the input. You might want to ignore them, or you might want to report a problem to the user.
If there are other characters, you might want to report a problem to the user.
Here's another approach, which you could use with a string of some maximum length (defined by the constant MAX_LEN).
A string made up of a bunch of char will use one byte per character, so you can define MAX_LEN up to how many bytes you have in system memory, generally, although in practice you probably would use a much smaller and more reasonable number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 12345
int main()
{
int digit, digits_checker[10] = {0}, flag = 0, i;
char* num;
/* set aside space for the string and its terminator */
num = malloc(MAX_LEN + 1);
/* read num from input */
scanf("%s", num);
/* get the string length */
size_t num_length = strlen(num);
/* walk over every character in num */
for (size_t position = 0; position < num_length; position++)
{
/*
We assume that the value of num[position] is an
ASCII character, from '0' to '9'. (If you can't make
that assumption, check the input and quit with an
error, if a non-digit character is found.)
If the input is valid, the digits 0-9 in the ASCII
table start at 48 ('0') and end at 57 ('9'). Subtracting
48, therefore, gives you the integer value at each digit
in num.
*/
digit = num[position] - 48;
/*
Increment a counter for each digit
*/
digits_checker[digit]++;
}
/* num is no longer needed, so we free its memory */
free(num);
/* check each digit */
for (i = 0; i < 10; i++)
{
if (digits_checker[i] > 1) {
printf("%d ", i);
flag = 1;
}
}
if (!flag) {
printf("The are no repeated digits.\n");
}
else {
printf("\n");
}
return 0;
}
The suggestion to check input is a good one. You can't necessarily assume that what someone enters will be entirely made up of digit characters.
But hopefully this demonstrates how to set aside space for a string, and how to read through it, one character at a time.
I'm crazy about this problem (Uva 455):
A character string is said to have period k if it can be formed by
concatenating one or more repetitions of another string of length k.
For example, the string ”abcabcabcabc” has period 3, since it is
formed by 4 repetitions of the string ”abc”. It also has periods 6
(two repetitions of ”abcabc”) and 12 (one repetition of
”abcabcabcabc”).
Write a program to read a character string and
determine its smallest period.
Input
The first line oif the input file
will contain a single integer N indicating how many test case that
your program will test followed by a blank line. Each test case will
contain a single character string of up to 80 non-blank characters.
Two consecutive input will separated by a blank line.
Output
An
integer denoting the smallest period of the input string for each
input. Two consecutive output are separated by a blank line.
Sample Input
1
HoHoHo
Sample Output
2
I've checked all test cases I could imagine and all of them returned correct result, but I still get Wrong Answer on the online judge. Where did I go wrong?
(English is not my native language; please excuse typing or syntax errors.)
#include <stdio.h>
#include <string.h>
#define maxn 85
int check(char* s, int per){
for(int i = 0; i < strlen(s) - per; i++){
if(s[i + per] != s[i]) return 0;
}
return 1;
}
int main(){
int T;
scanf("%d", &T);
char s[maxn];
while(T--){
scanf("%s", s);
int len = strlen(s);
bool OK = false;
for(int i = 1; i <= len/2 && (len % i == 0); i++){//That's wrong.
if(check(s, i)){
printf("%d\n", i);
OK = true;
break;
}
}
if(!OK) printf("%d\n", len);
if(T) printf("\n");
}
return 0;
}
The problem is in for(int i = 1; i <= len/2 && (len % i == 0); i++). You are stopping as soon as you encounter an i that doesn't divide len, instead of skipping it.
Write the loop as:
for (int i = 1; i <= len/2; i++) {
if (len % i != 0) continue;
...
}
The problem: Given a txt file, find the normalized frequencies of all the letters in the document.
For example if given letters.txt containing "aaabb"
Output would be:
Letter | Frequency
a 0.6
b 0.4
Non-letters or numbers should be ignored.
My solution so far:
Since they want to input a text file, my main() should receive command line arguments.
int main (int argc, char* argv[]){
I've made an EOF check using getchar()
while ((c=getchar()) != EOF){
and an if statement that checks if the char that getchar() is within the ASCII values for a->z or A->Z
if (argv[1][c] >= 'a' && argv[1][c] <= 'z' || argv[1][c] >= 'A' && argv[1]<= 'Z')
2 things here - I dont know if argv[1][c] is the right way to go about writing this but intuitively it made sense to me.
Once the check is satisfied, I want the corresponding letter to update a count specifically for its # position in the alphabet. Therefore needing a declared array that iterates for that letter each time it is found.
count[26];
Here is where I'm having troubles associating the letter a or A to position count[0] in the count array. I don't know how to code this part.
Why not create an int array that is of size 52 and have the first half of the array be for lower-case character counts and the upper half be for uppercase?
So in pseudocode:
#define ALPHA_COUNTS (52)
#define UPPER_OFFSET (26)
int counts[ALPHA_COUNTS] = {0};
for (char c : the_file_stream) {
if (c is an alphabet character) {
if (c is a lowercase character){
++counts[c - 'a'];
} else {
++counts[c - 'A' + UPPER_OFFSET];
}
}
}
Even easier would be to just create a table for all ASCII characters and just populate it for alphabet characters:
#define ASCII_COUNT (127)
int counts[ASCII_COUNT] = {0};
for (char c : the_file_stream) {
if (c is an alphabet character) {
++counts[c];
}
}
Then later on, you could just iterate through the set of [Aa-Zz] and check the counts of each of the characters.
Simplify the statistics gathering by counting the occurrence of all input.
Non-letters or numbers should be ignored in the result.
unsigned long long count[UCHAR_MAX + 1] = {0};
int ch;
while ((ch=getchar()) != EOF){
count[ch]++;
}
Now only sum the ones that are letters
unsigned long long sum = 0;
for (int i=0; i<=UCHAR_MAX; i++) {
if (isalpha(i)) {
sum += count[i];
// fold into lower case
if (isupper(i)) {
count[tolower(i)] += count[i];
count[i] = 0;
}
}
}
Print their frequency
for (int i=0; i<=UCHAR_MAX; i++) {
if (isalpha(i) && count[i] > 0) {
printf("%c %f\n", i, 1.0*count[i]/sum);
}
}
There are a number of different ways to approach the problem. You can make use the the functions provided in ctype.h (e.g. isalpha, tolower, toupper, etc.), or for the limited number of tests required, you can simply test the characters directly using arithmetic or basic bitwise operations. For example, you can test if a value is between 'a' and 'z' for lower-case, and for all characters the 6th-bit in 7-bit ASCII is the case-bit, so simply toggling the case-bit will change a character from upper-to-lower or vice versa.
The read then analyze approach chux outlined is an excellent approach to take. Any time you can separate input/output from processing data, you provide yourself a great deal of flexibility.
Using that logic, an example of using arithmetic and simple bitwise operations to analyze the frequency of alpha-characters ([A-Za-z]) which occur in a file can be written similar to the following. Note, the program will read from the filename provided as the first argument (or from stdin by default if no filename is given:
#include <stdio.h>
#include <limits.h>
int main (int argc, char **argv) {
unsigned long long count[UCHAR_MAX + 1] = {0}, sum = 0;
int c, i;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while ((c = fgetc(fp)) != EOF) count[c]++; /* fill count */
for (i = 0; i <= UCHAR_MAX; i++) {/* freq of only chars */
if ('A' <= i && i <= 'Z') { /* fold upper-case */
count[i ^ (1u << 5)] += count [i]; /* into lower */
count[i] = 0; /* zero index */
}
if ('a' <= i && i <= 'z') /* if lower-case */
sum += count[i]; /* add to sum */
}
printf ("\n total characters [A-Za-z]: %llu\n\n", sum);
for (i = 0; i <= UCHAR_MAX; i++)
if (count[i] > 0 && ('a' <= i && i <= 'z'))
printf (" %c%c : %.2f\n", i ^ (1u << 5), i, 1.0 * count[i]/sum);
putchar ('\n');
if (fp != stdin) fclose (fp); /* close if not stdin */
return 0;
}
Examples Use/Output
Using your example of 'aaabb' the program produces the following:
$ ./bin/char_freq < <(echo "aaabb")
total characters [A-Za-z]: 5
Aa : 0.60
Bb : 0.40
A slightly longer example shows the full character selection of only [A-Za-z]:
$ ./bin/char_freq < <(echo "*(a)123A_a/B+4b.")
total characters [A-Za-z]: 5
Aa : 0.60
Bb : 0.40
Look over this answer as well as all the others and let me know if you have additional questions.
The program I am writing to take a number and display that number as a calculator would display it (shown below) is compiling with no issues, but when I try to run it, I am able to input my number, but nothing happens. It seems like it is "hanging", since no further output is shown as I would have expected. Might anyone know what the problem is?
#include <stdio.h>
#define MAX_DIGITS 20
char segments[10][7] = /* seven segment array */
{{'1','1','1','1','1','1','0'}, /* zero */
{'0','1','1','0','0','0','0'}, /* one */
{'1','1','0','1','1','0','1'}, /* two */
{'1','1','1','1','0','0','1'}, /* three */
{'0','1','1','0','0','1','1'}, /* four */
{'1','0','1','1','0','1','1'}, /* five */
{'1','0','1','1','1','1','1'}, /* six */
{'1','1','1','0','0','0','0'}, /* seven */
{'1','1','1','1','1','1','1'}, /* eight */
{'1','1','1','0','0','1','1'}};/* nine */
char digits[3][MAX_DIGITS * 4]; /* digits array */
int i, j; /* count variables */
int adjust; /* output formatting */
int main(void) {
clear_digits_array();
int digit[20];
for (i = 0; i < 20; i++) {
digit[i] = 0;
}
int count = 20;
int position = 0;
printf("Enter a number: ");
int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&digit[0],
&digit[1],
&digit[2],
&digit[3],
&digit[4],
&digit[5],
&digit[6],
&digit[7],
&digit[8],
&digit[9],
&digit[10],
&digit[11],
&digit[12],
&digit[13],
&digit[14],
&digit[15],
&digit[16],
&digit[17],
&digit[18],
&digit[19]); //NOTHING HAPPENS AFTER HERE
printf("Got input, number is %d", number);
while (count > 0) {
printf("Reading digits, count is %d", count);
process_digit(digit[20 - count], position);
position++;
count--;
}
print_digits_array();
printf("\n");
return 0;
}
void clear_digits_array(void) {
/* fill all positions in digits array with blank spaces */
for (i = 0; i < 3; i++) {
for (j = 0; j < (MAX_DIGITS * 4); j++) {
digits[i][j] = ' ';
}
}
}
void process_digit(int digit, int position) {
/* check each segment to see if segment should be filled in for given digit */
for (i = 0; i < 7; i++) {
printf("Processing digit %d at position %d, i is %d", digit, position, i);
if (segments[digit][i] == 1) {
switch (i) {
case 0: digits[0][(position * 4) + 1] = '_';
break;
case 1: digits[1][(position * 4) + 2] = '|';
break;
case 2: digits[2][(position * 4) + 2] = '|';
break;
case 3: digits[2][(position * 4) + 1] = '_';
break;
case 4: digits[2][(position * 4) + 0] = '|';
break;
case 5: digits[1][(position * 4) + 0] = '|';
break;
case 6: digits[1][(position * 4) + 1] = '_';
break;
}
}
}
}
void print_digits_array(void) {
/* print each character in digits array */
for (i = 0; i < 3; i++) {
for (j = 0; j < (MAX_DIGITS * 4); j++) {
printf("%c", digits[i][j]);
}
printf("/n");
}
}
Your code includes:
printf("Enter a number: ");
int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&digit[0],
&digit[1],
&digit[2],
&digit[3],
&digit[4],
&digit[5],
&digit[6],
&digit[7],
&digit[8],
&digit[9],
&digit[10],
&digit[11],
&digit[12],
&digit[13],
&digit[14],
&digit[15],
&digit[16],
&digit[17],
&digit[18],
&digit[19]); //NOTHING HAPPENS AFTER HERE
Have you entered twenty separate digits? If not, scanf() is waiting for you to type some more numbers.
Note that the return value from scanf() is the number of successfully converted numbers (0..20 in the example), not the value you entered.
Is that the issue? I tried to make it such that the maximum amount of numbers the user could enter was 20, and if any more were entered they would be ignored, or if fewer were entered, it would only consider those (say, 5 were entered, then only the 5 would be used). Is there an easier way to do this sort of thing then?
Yes, I think that's the issue.
There are probably several easier ways to do it. I'd be tempted to use:
char buffer[22]; // 20 digits, newline, null
if (fgets(buffer, sizeof(buffer), stdin) != EOF)
{
size_t len = strlen(buffer);
if (len >= sizeof(buffer) - 1)
{
fprintf(stderr, "You entered too long a string (maximum 20 digits)\n");
exit(EXIT_FAILURE);
}
if (len > 0)
buffer[--len] = '\0'; // Zap newline — carefully
for (int i = 0; i < len; i++)
{
if (!isdigit(buffer[i]))
{
fprintf(stderr, "Non-digit %c found\n", buffer[i]);
exit(EXIT_FAILURE);
}
}
...and from here, process the digits in buffer, one at a time...
...Use buffer[i] - '0' to get a number 0..9 from the character in buffer...
}
Another option is to use a long long number, but that only gives you up to 18 digits (signed) or 19 digits (unsigned), with some values of 19 or 20 also within range. You'd then strip the digits out of the number using division and modulus operations.
long long value;
if (scanf("%lld", &value) == 1)
{
if (value < 0)
...error processing...
do
{
int digit = value % 10;
value /= 10;
...process digit...
} while (value > 0);
}
This has some merits, but in practice, I'd be tempted to use fgets() to read a line of input, and either sscanf() or strtoll() to convert and validate the number. That isn't as simple as it looks; the error returns from strtoll(), in particular, are many and subtle, and none of the scanf() family handle overflowing numbers gracefully. You could constrain the scanf() though with %18lld so that no more than 18 digits are read, but that would mean that if the user typed 19 or more digits, you'd get the leftovers on the next attempt to read with scanf(). So, handling scanf() is not simple either, especially if you need to convert multiple numbers in a single run of the program.
With those caveats out of the way, you can usually do a 'good enough' job with a sensible person providing the input. It is the process of making a program bomb-proof (foolproof — as in, proof against fools) that is hard. I find meaningful error reporting easier when I can report the whole string that was read in (as with fgets()); with scanf(), you can't see the characters that were entered and consumed before something went wrong.
use GDB, here is introduction for it http://www.gnu.org/software/gdb/
look into this tutorial too http://www.cs.cmu.edu/~gilpin/tutorial/
int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&digit[0],
&digit[1],
&digit[2],
&digit[3],
&digit[4],
&digit[5],
&digit[6],
&digit[7],
&digit[8],
&digit[9],
&digit[10],
&digit[11],
&digit[12],
&digit[13],
&digit[14],
&digit[15],
&digit[16],
&digit[17],
&digit[18],
&digit[19]);
I don't think this is a good idea use loop here
for (i = 0; i < 20; i++)
scanf("%d",&digit[i]);
And if you need the number
then do like this
int number = i; when loop finishes.
You can also try this
char buf[12];
while((c=getchar())!=EOF && i < 20)
{
buf[j++] =c;
if((c == '\n' || c == ' ' || c == '\t') && (sscanf(buf,"%d",&digit[i])) == 1)
{
i++;
j = 0;
}
}
For EOF you will have to press CTRL+D
In this way you can take 20 or less integers