我需要在檔案中找到最大的整數并列印出來。數字可以有超過 100 位數字,每個數字后面都有一個逗號,除了最后一個數字,后面什么都沒有。
示例 1:
-87654,-987,-23,-12344
示例 2:
12345123451234512345,678,90,12345123451234512346,12344
這是我的代碼:
#include <stdio.h>
int main() {
const char file[] = "numbers.txt";
FILE *fp = fopen(file, "r");
int c = fgetc(fp);
int prev = 0, max = 0, final_max, count = 1, start;
while (c != EOF) {
prev = max;
max = 0;
while (1) {
c = fgetc(fp);
count ;
max ;
if (c == 44 || c == EOF) {
count--;
break;
}
}
if (prev > max) {
final_max = prev;
start = count - final_max;
}
}
fclose(fp);
FILE *fp_fp = fopen(file, "r");
int i = 0;
while (1) {
c = fgetc(fp_fp);
i ;
if (i >= start && i < start final_max - 1)
printf("%c", c);
if (i == start final_max)
break;
}
fclose(fp_fp);
return 0;
}
fscanf不允許使用陣列、字串和函式
我的演算法如下(變數名稱在代碼中):
- 求最長數的位數 (
final_max) - 存盤不帶陣列的最長數的起始索引 (
start) - 最長數的最后一個索引是
start final_max - 1 - 關閉檔案并再次打開
- 當找到起始索引時,開始一個接一個地列印數字,直到到達最后一個索引
我這里有兩個問題:
這有時會在數字之前或之后添加額外的數字。
這不適用于負數。
你能幫我修改我的代碼以使其正常作業嗎?
uj5u.com熱心網友回復:
哪個數字更大?
- 999
- 1000
更長的數字更大。
哪個數字更大?
- 123
- 132
最左邊數字最大的數字更大。
這第二個需要稍微思考一下,才能看到它是正確的。只要最左邊的數字相同,就可以忽略。因此:
12345 --> 2345 --> 345 --> 45
12372 --> 2372 --> 372 --> 72 --> (7 > 4) therefore (12372 > 12345)
哪個數字更大?
- -7
- 5
正數總是大于負數。
哪個數字更大?
- -123
- -132
這兩個數字都是負數,這使得答案與它們都是正數時的結果相反。換句話說, 123 < 132因此-123 > -132。
使這變得困難的是禁止使用任何型別的陣列(字串)的禁令。我繼續假設這包括當前最大的數字。
不幸的是,您當前的代碼在邏輯上有點混亂……
在撰寫一大堆代碼之前,您需要更多地考慮打算如何解決問題。這里有一些提示:
我們不能存盤字串,但我們可以ftell()使用和跟蹤檔案中的讀取位置fseek()。
Something else we can do to make life easier is to open the input file twice — once for the current largest number and once for the current number being compared. This allows us to use the standard fgetc() for each file without having to fseek() back and forth for every digit of the two numbers.
You should write yourself a function to compare two numbers from the two file objects:
int compare( FILE * lhs, FILE * rhs );
// returns -1 if lhs < rhs
// returns 0 if lhs == rhs
// returns 1 if lhs > rhs
This function is really the hardest part. In my own solution I found that the following functions were also helpful:
int fpeek( FILE * f )
{
int c = fgetc( f );
ungetc( c, f );
return c;
}
int sign( FILE * f );
// returns -1 or 1
// if the next character in f is a '-':
// then discard it and return -1 (negative)
// else return 1 (positive)
int next( FILE * f );
// Returns a digit '0'..'9'
// or 0 if end of number (character was a ',' or EOF)
void skip( FILE * f )
// Skip to next number
{
while (next( f )) { }
}
The principles I outlined above are what you need to test the numbers. The hardest part of it is working with comparing length and value. I wrote mine doing both things at once, but you might find it easier to do more or less what you were initially thinking:
- Compare signs. If different you’re done!
(largest is the non-negative one) - Compare lengths. If different you’re done!
(largest is the longest if sign==1, the shortest if sign==-1) - Seek back and compare values. First difference and you’re done!
largest is first larger value if sign==1, ... - No differences, you’re done: (a==b)!
Remember that the sign stuff flips the result between -1 and 1. You can do this with an easy multiplication. For example, if you wished to return that lhs was the larger number if it were positive then return -1 * sign;.
The next kind of hard part is in main(), but this is easier than the comparison function at least. You just need to find the beginning of each number in a loop and do a comparison. Remember to use ftell() to be able to reset the positions after calling compare() and skip() to the next number.
FILE * f_largest = fopen( "numbers.txt", "r" );
FILE * f_current = fopen( "numbers.txt", "r" );
The f_largest file object is for the currently-largest number.
The f_current file object is for looping through the numbers to compare.
This part of the algorithm works like any “find the max number” algorithm: keep track of the largest number found until you have looked at all the numbers. Do you see how using two file objects makes this easy?
while current is not at EOF:
position of largest = ftell largest
position of current = ftell current
compare largest and current. If current > largest:
largest position = current position
fseek in largest to position of largest
fseek in current to position of current
skip current to next
Once you have finished the main loop you just need to print the number at f_largest.
Evil homeworks!
This stuff is designed to stretch your brain really hard. This particular assignment, IMHO, is a little over-the-top for a CS 101, but it should still be doable.
These kinds of assignments do get tricker as you go. The whole point is for you to struggle until you can wrap your brain around a solution. The more you can figure that solution yourself the better.
It certainly helps to have more experience with programming in general, though. This assignment kind of assumes a few jumps that I don’t think are really under your belt yet, but I could be wrong abouty what level you are expected to function.
In any case, hopefully this edit has made things more clear in terms of how to handle this. The underlying point is that a file is just another source of characters, just like a string. You simply have to access it with seek and get functions instead of array indexing.
That, and you will notice that I (regularly) advocate for little helper functions. Split your task into smaller pieces and it becomes much more manageable.
uj5u.com熱心網友回復:
不使用陣列或字串的限制有點困難,并且會阻止流處理,因為您必須能夠向后搜索。
這是Dúthomhas描述的方法的實作。但請注意,它不處理前導零、 符號或空格:
#include <stdio.h>
int is_digit(int c) { return c >= '0' && c <= '9'; }
int main() {
const char file[] = "numbers.txt";
FILE *fp = fopen(file, "r");
FILE *fp2 = fopen(file, "r");
long largest = 0, current = 0;
int c, c2, cmp = 0, neg = 0, neg2 = 0;
for (;;) {
c = getc(fp);
if (c == '-') {
neg = 1;
c = getc(fp);
}
c2 = getc(fp2);
if (c2 == '-') {
neg2 = 1;
c2 = getc(fp2);
}
if (is_digit(c)) {
if (is_digit(c2)) {
if (cmp == 0)
cmp = c - c2;
continue;
}
/* number is longer than largest */
cmp = 1;
} else
if (is_digit(c2)) {
/* current is shorter */
cmp = -1;
} else {
/* current and largest have the same length */
}
if (neg) {
if (neg2 && cmp < 0)
largest = current;
} else {
if (neg2 || cmp > 0)
largest = current;
}
fseek(fp2, largest, SEEK_SET);
/* skip remaining digits */
while (is_digit(c))
c = getc(fp);
current = ftell(fp);
cmp = neg = neg2 = 0;
if (c == EOF)
break;
}
while ((c = getc(fp2)) != ',' && c != EOF)
putchar(c);
putchar('\n');
fclose(fp);
fclose(fp2);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/436654.html
上一篇:C函式在字串陣列中加載檔案內容
