Still working on it but when I try to run the program I keep getting the error. I'm very new to programming so can't even see any issues at this point.
This is an assignment for the CS50 course; called credit card.
Also any constructive comments would be highly appreciated :)
Code is below.
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
int main(int argc, string argv[])
{
int n = 0; //n is length of card number
int i = 0; //i is the digit
int m = 0;
int p = 0;
string s = 0;
do
{
printf("Card Number: \n");
string s = GetString(); //card number
n = strlen(s);
printf("%s\n", s);
for (i = 0; i<n; i++)
{
if (i %2 == 0)
{
m = ((s[i] - '1')*2);
if (m < 10)
{
p = p + m; //p is product m is numerical value
}
else
{
p = 1 + p + (m -10);
}
}
else
{
p = p + (s[i] - '1');
}
}
if (p % 10 ==0)
{
if (n == 15 && s[1] == 3 && (s[2] == 4 | s[2] == 7))
{
printf("AMEX\n");
}
if (n == 16 && s[1] == 5 && (s[2] == 1 | s[2] == 2 | s[2] == 3 | s[2] == 4 | s[2] == 5))
{
printf("MASTERCARD\n");
}
if ((n == 3 | n==16) && s[1] == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
}
// while ();
}
Try removing the first declaration of string.
Also, I see that the while condition in the do-while loop is commented out. If it is meant to be used for the input though, the for loop which iterates over the string to analyze the number shouldn't be included in it. The do-while loop should terminate after the input is received and the program should then progress to the for loop.
Related
So here is the problem:
Input a string contains of numbers from 0 to 9 (maximum length is 15)
If the left most character divisible by 3, remove it from the string
If the right most character divisible by 3, remove it from the string
If the string does not match the above two conditions, and if the summary of the left most character and the right most character is divisible by 3, remove them from the string.
Keep doing so until the string is NULL or not meet the above conditions.
Example: input: "312248" ---> output: 2.
input: "366936363" ---> output: ""
So here is my code:
#include <stdio.h>
#include <stdbool.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
char* truncateString(char* s)
{
char *p = &s[0];
int n = strlen(s);
p = calloc(n,sizeof(char));
int flag = 1;
do{
for (int i = 0; i < strlen(s); i++)
{
if ((s[0]-'0') % 3 == 0)
{
for(int j = 0; j < strlen(s); j++)
{
s[j] = s[j+1];
}
p = realloc(p, (strlen(s)-1)*sizeof(char));
}
else if ((s[strlen(s)-1]-'0') % 3 == 0)
{
p = realloc(p, (strlen(s)-1)*sizeof(char));
}
else if (((s[strlen(s)-1]-'0')+(s[0]-'0')) % 3 == 0)
{
for(int j = 0; j < (strlen(s)-1); j++)
{
s[j] = s[j+1];
p = realloc(p, (strlen(s)-2)*sizeof(char));
}
}
else
{
flag = 0;
}
}
} while (strlen(s) != 0 || flag != 0);
free(p);
return s;
}
int main()
{
char s[100];
gets(s);
printf("Result:%s", truncateString(s));
getch();
return 0;
}
I honestly do not know how to check if the character is divisible by 3 or not, so the code is not running.
I'd consider a re-write that clearly matches the coding goals to fix functional errors.
(s[0]-'0') % 3 == 0 is a fine way to test for divisibility as s[0]-'0' provides the textual char to int value.
It is often useful to put the goals in as comments right where they are used.
strlen() needs to be called just once. Update the length as needed. This avoids repetitive calls to strlen(), each costing O(len).
char* truncateString(char *s) {
char *start = s;
size_t len = strlen(s);
// Keep doing so until the string is "NULL"
while (len > 0) {
char left = s[0] - '0';
bool left_remove = left % 3 == 0;
char right = s[len - 1] - '0';
bool right_remove = right % 3 == 0;
bool right_differ_from_left = len > 1;
// If the left most character divisible by 3, remove it from the string
if (left_remove) {
s++;
len--;
}
// Only consider the 'right' if the string was more than 1.
if (right_differ_from_left) {
// If the right most character divisible by 3, remove it from the string
if (right_remove) {
len--;
s[len] = '\0';
}
// If the string does not match the above two conditions,
// and if the summary of the left most character and
// the right most character is divisible by 3,
// remove them from the string.
if (!left_remove && !right_remove && (left + right) % 3 == 0) {
s++;
len -= 2;
s[len] = '\0';
left_remove = right_remove = true;
}
}
// Keep doing so until the string is ... not meet the above conditions.
if (!left_remove && !right_remove) {
break;
}
}
// Move string to its original beginning.
return memmove(start, s, len + 1);
}
If the coding goals are stable, simplifications exists. Yet notice that this may be faster, it is harder to see it matches the coding goals than the above.
char* truncateString2(char *s) {
char *start = s;
size_t len = strlen(s);
size_t len_at_loop_start;
do {
len_at_loop_start = len;
while (len > 0 && (s[0] - '0') % 3 == 0) {
s++;
len--;
}
while (len > 0 && (s[len-1] - '0') % 3 == 0) {
len--;
}
while (len > 1 && (s[0] - '0' + s[len-1] - '0') % 3 == 0) {
s++;
len -= 2;
}
} while (len < len_at_loop_start);
s[len] = '\0';
return memmove(start, s, len + 1);
}
You are having troubles with reallocation too. Try this, it may make things easier
char* truncateString(char* s)
{
int n = strlen(s);
int flag = 1;
while (strlen(s) != 0 && flag != 0){
if ((s[0]-'0') % 3 == 0)
s++;
else if ((s[strlen(s)-1]-'0') % 3 == 0)
s[strlen(s)-1] = '\0';
else if (((s[strlen(s)-1]-'0')+(s[0]-'0')) % 3 == 0)
{
s++;
s[strlen(s)-1] = '\0';
}
else
flag = 0;
}
return s;
}
Quick explanation: when you declare s++ you are preciselly removing the first element of the array, and using s[strlen(s)-1] = '\0' removes the last element.
EDIT:
Another solution here, that will work faster. Instead of calling s[strlen(s)-1] each time, you can just keep track of the initial n=strlen(s); Also, removed the -'0', because ASCII codes for numbers start in 48, so they are in the right position for checking divisibility by 3. Thanks to #chux-ReinstateMonica. Here is the code:
char* truncateString(char* s)
{
int n = strlen(s);
int flag = 1;
while (n != 0 && flag != 0){
if ((s[0]) % 3 == 0){
s++;
n--;
}
else if ((s[n-1]) % 3 == 0)
s[--n] = '\0';
else if (((s[n-1])+(s[0])) % 3 == 0)
{
s++;
n--;
s[--n] = '\0';
}
else
flag = 0;
}
return s;
}
**
Hello :)
So I have this task to write a program that will convert int to arg using malloc and well it all works fine, gdb shows no errors, but it is not printing any output in this form. If i delete itoa_buffer[i] = '\0'; than sometimes it shows output sometimes not. I do not know what is wrong here, seems fine.
I do not know where to ask for help as I like to follow my logic and find errors here instead of copying solutions from the internet. I willl appreciate some tips, its probably some small thing Id do not know and wont let me go further.**
#include<stdio.h>
#include "libft.h"
char *ft_itoa(int n)
{
int i;
int z;
char x;
char *itoa_buffer;
if (n == INT_MIN)
return(ft_strdup("-2147483648"));
if (n < 0)
{
n = -n;
z = n;
i = 1;
}
else
{
z = n;
i = 0;
}
while(z > 0)
{
z = z/10;
i++;
}
if(!(itoa_buffer = (char *)malloc((i+1)*sizeof(char))))
return(0);
i = i + 1;
while(--i)
{
x = (n%10 + '0');
itoa_buffer[i] = x;
n = n/10;
if(n == 0 && i == 2)
{
i--;
itoa_buffer[i] = '-';
i--;
break;
}
}
itoa_buffer[i] = '\0'; // it stopped showing answers when i tried to add this symbol at the end.
return(itoa_buffer);
}
int main()
{
int n;
n = 1980;
printf("%s", ft_itoa(n));
}
You are putting '\0' as the first character of the string.
Instead of that, you should put that as the last character.
Instead of this part
i = i + 1;
while(--i)
{
x = (n%10 + '0');
itoa_buffer[i] = x;
n = n/10;
if(n == 0 && i == 2)
{
i--;
itoa_buffer[i] = '-';
i--;
break;
}
}
itoa_buffer[i] = '\0';
you should do this
itoa_buffer[i] = '\0';
while(i--)
{
x = (n%10 + '0');
itoa_buffer[i] = x;
n = n/10;
if(n == 0 && i == 1)
{
i--;
itoa_buffer[i] = '-';
break;
}
}
I'm trying to create a c program that checks if the password contains at least :
-1 special character
-1 lowercase letter
-1 uppercase letter
-1 digit
when i test it, it doesn't work for some reason i've been trying to figure out my error but i didn't know what was wrong
this is my attemp :
//check password =at least one upper /at least 1 lower/ at least 1 char;
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
void main() {
char pass[20]; //password
int a = 0; //size of the password
int foundChar = 0;
int foundUpper = 0;
int foundLower = 0;
int foundDigit = 0;
int i = 0;
do {
printf("enter your password : ");
scanf("%s", pass);
a = strlen(pass);
if (a = 8) {
if (isdigit(pass[i]) && foundDigit == 0) {
foundDigit = 1;
i++;
} else if (isupper(pass[i]) && foundUpper == 0) {
foundUpper = 1;
i++;
} else if (islower(pass[i]) && foundLower == 0) {
foundLower = 1;
i++;
} else if (foundChar == 0) {
foundChar = 1;
i++;
}
}
}
while ((a < 8) || (foundChar == 0) || (foundDigit == 0) || (foundUpper == 0) || (foundUpper = 0));
}
You are not looping through the password.
After your if (a >= 8) statement, there is no code to loop around and examine the remaining characters in the string.
I'm trying to pass back an updated char array to the original main() function, however when i try to copy over the array with a pointer before it it gives me "Char " differs in levels of indirection from char() [15]'
This is a ISBN validator program.
Here it is:
int main(void)
{
int divisible;
char choice, trash;
char code[15];
do
{
printf("Enter an ISBN (book) number:\n");
fgets(code, 15, stdin);
printf("The ISBN entered is:%s\n", code);
divisible = testISBN(&code);
if (divisible == 1)
printf("\n\n\tValid ISBN Number\n");
else
printf("\n\n\tInvalid ISBN Number\n");
printf("\nDo you wish to continue? (Y/N)\n");
choice = getchar();
trash = getchar();
} while (toupper(choice) != 'N');
return 0;
}
int testISBN(char *code)
{
int i;
int sum = 0;
int weight = 10;
char codefinal[10];
int x = 0;
for (i = 0; i<15; i++)
{
int chVal;
if ((i == 9) && (toupper(code[i]) == 'X'))
{
printf("%c",code[i]);
chVal = 10;
}
else
{
chVal = code[i] - '0';
}
if (chVal == 0 || chVal == 1 || chVal == 2 || chVal == 3 || chVal == 4 || chVal == 5 || chVal == 6 || chVal == 7 || chVal == 8 || chVal == 9) {
char y = (char)chVal;
codefinal[x] = y;
x++;
}
sum += chVal * weight;
weight--;
}
printf("sum is %d", sum);
for (i = 0; i < 15; i++) {
*code[i] = codefinal[i];
printf("%c", code);
}
return (sum % 11) == 0;
}
At the very bottom where i said *code[i] = codefinal[i] is where i get the issue. I'm just trying to pass back by pointer my new updated array of numbers to my main.
Do following changes in your code:
Change prototype of function int testISBN(char* code) to int testISBN(char code[])
Change calling from testISBN(&code); to testISBN(code);
Change line *code[i] = codefinal[i]; to code[i] = codefinal[i];
In line printf("%c", code); you are printing not the value but the address of code[]. So change it to printf("%c", code[i]);. Note that code[] contains some non printable characters also.
Suggestion: You can change line if (chVal == 0 || chVal == 1 || chVal == 2 || chVal == 3 || chVal == 4 || chVal == 5 || chVal == 6 || chVal == 7 || chVal == 8 || chVal == 9) to if((chVal >= 0) && (chVal <= 9)) for simplicity.
Just pass code as is it will decay into pointer.
char code[15];
divisible = testISBN(code);
You may want to change testISBN signature to
int testISBN(char code[15]);
This way you have a higher chances to get compiler warning if you mess up indices.
Simple example:
#include <stdio.h>
void func(char arr[3]) {
arr[0] = 'H';
arr[1] = 'i';
arr[2] = 0;
}
int main() {
char arr[3] = {0};
func(arr);
printf("%s", arr);
}
Prints "Hi"
As commenters mentioned your code has other issues such as memory out of bounds access. To ease your life spend some time with your compiler's manual and learn how to turn on all the warnings, they indicate code issues most of the time.
My intent with this code is to make a vignere cipher.
I can compile my code with gcc but when I run the program and pass 2 strings in the command line I have a segmentation fault. Initially I had tried to control the int value of j with a separate if-statement in my for-loop such as:
if( i % strlen(msg) == 0) {
j = 0;
}
else {
j++;
}
However, it was not clear to me if this would produce my intended result, to execute an expression in this if-statement and to then continue with the next if-statement. So, I substitute a conditional statement and the code compiles. However, in both cases I get a segmentation fault, using either method with j.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *msg = argv[1];
char *key = argv[2];
int i, j, sl, ky, mg;
sl = strlen(key);
j = 1;
int encrypt[strlen(msg)];
if(isalpha(key) && argc == 3) {
;
}
else
perror("run program from cmd line with 2 strings \n");
return 1;
for(i = 1; i <= sl; i++) {
(i % strlen(key) == 0) ? j = 0 : j++;
mg = msg[i];
ky = key[j];
if(isalpha(msg[i])) {
if(isupper(msg[i])) {
msg[i] = 'A' + (('A' - msg[i]) + ('A' - key[j]) % 26);
}
else if(islower(msg[i])) {
msg[i] = 'a' + (('a' - msg[i]) + ('a' - key[j]) % 26);
}
else {
msg[i] = msg[i];
}
}
}
return 0;
}
Okay well I fixed some oversights such as lines 38 and 42. This snippet of code works as a cipher but it only works some of the time.
for(i = 0; i < sl; i++) {
(i % strlen(key) == 0) ? j = 0 : j++;
mg = msg[i];
ky = key[j];
if(isalpha(msg[i])) {
if(isupper(msg[i])) {
encrypt[i] = 'A' + ((( msg[i] - 'A') + (key[j]) - 'A') % 26);
}
else if(islower(msg[i])) {
encrypt[i] = 'a' + (((msg[i] - 'a') + (key[j]) - 'a') % 26);
}
else {
encrypt[i] = msg[i];
}
}
}
for(i = 0; i < strlen(msg); i++) {
printf("%c", encrypt[i]);