2012-04-06 36 views
7

Tôi đang thực hiện bài tập về nhà cho khóa học của tôi trong C (khóa học lập trình đầu tiên). Một phần của nhiệm vụ là viết mã để người dùng nhập số lên đến 9 chữ số và chương trình cần xác định xem con số này có "tăng"/"thực sự tăng"/"giảm"/"thực sự giảm" hay không "tăng và giảm"/"thực sự giảm và thực sự tăng"/"không giảm và không tăng". (7 lựa chọn trong tổng số)Trích xuất các chữ số riêng lẻ từ một số trong C

Vì đây là nhiệm vụ đầu tiên của chúng tôi chúng tôi không được phép sử dụng bất cứ điều gì ngoài những gì được dạy trong lớp:

do-while, for, vòng lặp while, khác-nếu, nếu, nghỉ ngơi, tiếp tục scanf, printf, modulo, và các nhà khai thác cơ bản

(Chúng ta không thể sử dụng bất kỳ thư viện bên cạnh cho stdio.h)

Vậy là xong. Tôi không thể sử dụng mảng hoặc getchar hoặc bất kỳ nội dung nào trong số đó. Chức năng duy nhất tôi có thể sử dụng để nhận dữ liệu nhập từ người dùng là scanf.

Cho đến giờ tôi đã viết thuật toán bằng sơ đồ và mọi thứ, nhưng tôi cần tách đầu vào của người dùng thành các chữ số riêng biệt. Ví dụ: nếu người dùng nhập "1234 ..." tôi muốn lưu 1 trong một, 2 trong b, v.v., sau đó thực hiện so sánh giữa tất cả các chữ số để xác định ví dụ xem chúng có bằng nhau hay không (tăng và giảm) hoặc liệu a> b> c ... (giảm) và vân vân.

Tôi biết cách tách từng chữ số bằng cách sử dụng toán tử% và /, nhưng tôi không thể tìm ra cách "lưu" các giá trị này trong biến mà sau này tôi có thể sử dụng để so sánh.

Đây là những gì tôi có cho đến nay:

printf("Enter a positive number : "); 

do { 
    scanf ("%ld", &number); 
    if (number < 0) { 
     printf ("invalid input...enter a positive integer: "); 
     continue; 
    } 
    else break; 
} while (1); 

while (number < 0) { 
    a = number % 10; 
    number = number - a; 
    number = number/10; 
    b = a; 
} 
+2

Chờ, họ muốn bạn chia một số thành số "tối đa 9", nhưng chúng sẽ không cho phép bạn sử dụng mảng? Thats ... đó chỉ là tàn nhẫn! –

+0

chỉ là phần đầu tiên ... một phần khác liên quan đến lý thuyết goldbach, người dùng nhập bất kỳ số nào lên đến 9 chữ số và đầu ra máy tính là số nguyên tố đầu tiên cộng với số đó. cùng một giới hạn cho điều đó cũng như – nofe

+2

Tôi không hiểu khái niệm của bạn về tăng và thực sự tăng lên. Và "tăng và giảm" là gì và "thực sự giảm và thực sự tăng". Vui lòng làm rõ cách mã của bạn được cho là phân loại đầu vào. – abelenky

Trả lời

4

Tại sao không quét chúng như ký tự (string)? Sau đó, bạn có thể truy cập chúng thông qua một mảng bù đắp, bằng cách trừ bù đắp của 48 từ mã ký tự ASCII. Bạn có thể xác minh rằng ký tự là một chữ số sử dụng isdigit từ ctype.h.


EDIT

Do những hạn chế vô cùng đãng trí mà giáo sư của bạn đưa ra:

#include <stdio.h> 

int main() 
{ 
    int number; 
    printf("Enter a positive number: "); 

    do 
    { 
    scanf ("%ld", &number); 
    if (number < 0) 
    { 
     printf ("invalid input...enter a positive integer: "); 
     continue; 
    } 
    else break; 
    } while (1); 

    int a = -1; 
    int b = -1; 
    int c = -1; 
    int d = -1; 
    int e = -1; 
    int f = -1; 
    int g = -1; 
    int h = -1; 
    int i = -1; 

    while (number > 0) 
    { 
    if (a < 0) a = number % 10; 
    else if (b < 0) b = number % 10; 
    else if (c < 0) c = number % 10; 
    else if (d < 0) d = number % 10; 
    else if (e < 0) e = number % 10; 
    else if (f < 0) f = number % 10; 
    else if (g < 0) g = number % 10; 
    else if (h < 0) h = number % 10; 
    else if (i < 0) i = number % 10; 

    number /= 10; 
    } 

    /* Printing for verification. */ 

    printf("%i", a); 
    printf("%i", b); 
    printf("%i", c); 
    printf("%i", d); 
    printf("%i", e); 
    printf("%i", f); 
    printf("%i", g); 
    printf("%i", h); 
    printf("%i", i); 

    return 0; 
} 

Những con số hợp lệ ở cuối sẽ là tích cực, vì vậy đó là những những người bạn xác thực để đáp ứng các điều kiện khác nhau của bạn.

+2

tôi liệt kê các giới hạn mà tôi có cho bài tập này ở trên ... hỏi "tại sao không chỉ làm điều này" hoặc điều đó không liên quan. Bạn cũng có thể hỏi tôi tại sao tôi thậm chí còn học C (tại sao không phải Java? C++?). Tôi vì đó là điều mà trường đại học yêu cầu của tôi về tôi – nofe

+2

Nếu bạn có thể quét số nguyên, bạn có thể quét ký tự. Một mảng bù đắp cơ bản là bổ sung, đáp ứng giới hạn của các toán tử cơ bản. –

+0

Tôi có thể quét ký tự, bạn nói đúng. Bạn có thể giải thích làm thế nào để làm một mảng bù đắp mà không sử dụng một mảng (không biết những gì một mảng là) như cho isdigit tôi không thể sử dụng đó hoặc bất kỳ thư viện khác ngoài stdio.h nhưng đó là ok vì tôi không cần phải xác minh rằng các ký tự thực sự là chữ số, người dùng chỉ nhập số nguyên. – nofe

1

Hãy để chúng tôi giả sử bạn có con số này 23654

23654 % 10000 = 2 and 3654 
3654 % 1000 = 3 and 654 
654 % 100 = 6 and 54 
54 % 10 = 5 and 4 
4 

Bằng cách này bạn có thể nhận được tất cả các chữ số. Tất nhiên, bạn phải biết nếu số lớn hơn 10000, 1000, 100 hoặc 10, để biết ước số đầu tiên.

Chơi với sizeof để lấy kích thước của số nguyên, để tránh một số lượng lớn nếu ...else statement

EDIT:

Chúng ta hãy xem

if (number>0) { 
    // Well, whe have the first and only digit 
} else if (number>10) { 
    int first_digit = number/10; 
    int second_digit = number % 10; 
} else if (number>100) { 
    int first_digit = number/100; 
    int second_digit = (number % 100)/10; 
    int third_digit = (number % 100) % 10; 
} ... 

và như vậy, tôi cho rằng

+0

Tôi cần phải đặt điều này vào vòng lặp vì tôi cần xử lý tối đa 9 chữ số. Ngoài ra, tôi muốn "lưu" các chữ số đó ở đâu đó hoặc gán chúng cho các biến để tôi có thể sử dụng chúng để so sánh của tôi – nofe

+0

không thể sử dụng sizeof .... các câu lệnh if-else lớn là tốt – nofe

0

Dưới đây là một ví dụ làm việc tại đồng bằng C:

#include <stdio.h> 

unsigned long alePow (unsigned long int x, unsigned long int y); 

int main(int argc, const char* argv[]) 
{ 
    int enter_num, temp_num, sum = 0; 
    int divisor, digit, count = 0; 

    printf("Please enter number\n"); 
    scanf("%d", &enter_num); 

    temp_num = enter_num; 

    // Counting the number of digits in the entered integer 
    while (temp_num != 0) 
    { 
     temp_num = temp_num/10; 
     count++; 
    } 

    temp_num = enter_num; 

    // Extracting the digits 
    printf("Individual digits in the entered number are "); 
    do 
    { 
     divisor = (int)(alePow(10.0, --count)); 
     digit = temp_num/divisor; 
     temp_num = temp_num % divisor; 

     printf(" %d",digit); 
     sum = sum + digit; 
    } 
    while(count != 0); 

    printf("\nSum of the digits is = %d\n",sum); 

    return 0; 
} 


unsigned long alePow(unsigned long int x, unsigned long int y) { 

    if (x==0) { return 0; } 
    if (y==0||x==1) { return 1; } 
    if (y==1) { return x; } 
    return alePow(x*x, y/2) * ((y%2==0) ? 1 : x); 
} 
+0

cảm ơn, một số điều này hữu ích . Tôi không muốn tổng hợp các chữ số mặc dù tôi muốn so sánh giữa chúng. Ngoài ra tôi không thể sử dụng math.h – nofe

+0

Cập nhật mà không sử dụng math.h, hãy xem hàm alePow;) – aleroot

1

Đó là ngu ngốc để yêu cầu bạn làm các vòng mà không có mảng --- nhưng t mũ của giáo viên của bạn lỗi, không phải của bạn.

Điều đó đang được nói, tôi sẽ làm một cái gì đó như thế này:

char c; 
while (1) { 
    scanf("%c", &c); 
    if (c == '\n') /* encountered newline (end of input) */ 
     break; 
    if (c < '0' || c > '9') 
     break;  /* do something to handle bad characters? */ 
    c -= '0'; 
    /* 
    * At this point you've got 0 <= c < 9. This is 
    * where you do your homework :) 
    */ 
} 

Bí quyết ở đây là khi bạn gõ số vào một chương trình, bạn gửi bộ đệm tất cả cùng một lúc, không phải là một nhân vật tại một thời điểm. Điều đó có nghĩa là lần quét đầu tiên sẽ chặn cho đến khi toàn bộ chuỗi (tức là "123823" hoặc bất kỳ thứ gì) đến cùng một lúc, cùng với ký tự dòng mới ('\ n'). Sau đó, vòng lặp này phân tích cú pháp chuỗi đó khi giải trí.

Sửa Đối với thử nghiệm tăng/giảm-Ness của các chữ số, bạn có thể nghĩ rằng bạn cần phải lưu trữ toàn bộ chuỗi, nhưng đó là không đúng sự thật. Chỉ cần xác định một số biến thêm để ghi nhớ thông tin quan trọng, chẳng hạn như:

int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far; 

vv vv

+0

cảm ơn, tôi thực sự đã biết cách xác minh tính hợp lệ của đầu vào nhưng bạn thuyết phục tôi cân nhắc sử dụng lại char. parse nghĩa là gì? – nofe

+1

"Phân tích cú pháp" có nghĩa là phân tích (gần đúng). Kiểu dữ liệu 'char' giống như' int' nhưng nhỏ hơn: Nó chỉ có thể xử lý các số trong phạm vi -128 đến 127 (nhưng điều đó tốt cho một chữ số duy nhất chỉ có thể là 0-9). Lý do tôi sử dụng 'char' là bởi vì tôi muốn sử dụng'% c' mà chỉ đọc chính xác một chữ số. Nhưng 'scanf' yêu cầu bạn sử dụng' char' để sử dụng '% c'. Ngoài ra, nó cũng có thể là 'int' thay vì' char' --- nó chỉ lưu trữ một số. –

0

tôi sẽ đề nghị loop-unrolling (bỏ qua hạn này nếu bạn không biết điều này).

int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits 
int count = 0; //for number of digits in the given number 


if(number>0) { 
i=number%10; 
number/=10; 
count++; 
} 

if(number>0) { 
h=number%10; 
number/=10; 
count++; 
} 

if(number>0) { 
g=number%10; 
number/=10; 
count++; 
} 
.... 
.... 
/* All the way down to the storing variable a */ 

Bây giờ, bạn biết số chữ số (số biến) và chúng được lưu trữ trong đó các biến. Bây giờ bạn có tất cả các chữ số và bạn có thể kiểm tra "giảm" của họ, "tăng" vv với rất nhiều nếu!

Tôi thực sự không thể nghĩ ra lời giải thích tốt hơn cho tất cả các điều kiện của bạn.

+0

OK, tôi nghĩ tôi có thể cắt góc với một vòng lặp lớn mà làm tất cả, nhưng theo những gì bạn đang nói tôi sẽ phải làm điều đó theo cách này. Tôi đã có điều này đã được bản thân mình tôi đã chỉ hy vọng cho một phím tắt. cảm ơn – nofe

+0

Bởi vì điều kiện của bạn làm cho nó thực sự khó khăn để viết một giải pháp tốt hơn cho điều này :) –

+0

@ nofe bạn có thể sử dụng một vòng lặp và bạn gần như chắc chắn nên sử dụng một vòng lặp ở đây! 'int a, b, c, d ...' giống với 'int digits [9]', vì vậy nếu bạn có một mảng thì bạn có thể dễ dàng lặp qua tất cả các chữ số. – Kiril

1

Vì bạn chỉ cần phải so sánh chữ số liên tiếp, có một cách thanh lịch để làm điều này mà không cần mảng:

int decreasing = 2; 
int increasing = 2; 

while(number > 9) 
{ 
    int a = number % 10; 
    int b = (number/10) % 10; 

    if(a == b) 
    { 
    decreasing = min(1, decreasing); 
    increasing = min(1, increasing); 
    } 
    else if(a > b) 
    decreasing = 0; 
    else if(a < b) 
    increasing = 0; 

    number /= 10; 
} 

Ở đây, chúng tôi đi bộ qua số (bằng cách chia cho 10) cho đến khi chỉ có một chữ số còn lại. Chúng tôi lưu trữ thông tin về con số cho đến thời điểm này trong decreasingincreasing - một số 2 có nghĩa là tăng/giảm thực sự, 1 có nghĩa là tăng/giảm và 0 có nghĩa là không tăng/giảm.

Ở mỗi bước, a là các chữ số và b là hàng chục. Sau đó, chúng tôi thay đổi increasingdecreasing dựa trên so sánh giữa ab.

Cuối cùng, nên dễ dàng biến các giá trị của increasingdecreasing thành câu trả lời cuối cùng mà bạn muốn.

Lưu ý: Hàm min trả về nhỏ hơn 2 đối số của nó.Bạn có thể tự viết, hoặc thay thế các dòng đó bằng câu lệnh if hoặc điều kiện.

Các vấn đề liên quan