使用MATLAB重新进货(低级别I/O)
又到了I/O让我困惑的时候了。在本例中,我的目标是编写一个函数,该函数接收库存项目的.txt文件和价格的另一个.txt文件,并输出重新进货项目的总成本,以及包含原始库存数据和需要重新进货的项目数量的.txt文件。例如:使用MATLAB重新进货(低级别I/O),matlab,if-statement,file-io,while-loop,low-level-io,Matlab,If Statement,File Io,While Loop,Low Level Io,又到了I/O让我困惑的时候了。在本例中,我的目标是编写一个函数,该函数接收库存项目的.txt文件和价格的另一个.txt文件,并输出重新进货项目的总成本,以及包含原始库存数据和需要重新进货的项目数量的.txt文件。例如: Inventory Data: Buns #50 #63 Burgers #32 #55 Ketchup #6 #10 Hotdogs #4 #35 Mustard #7 #8 注意:头文件包含在.txt文件中,并且始终有五个项目需要重新进货 我的输出文件应为: Invent
Inventory Data:
Buns #50 #63
Burgers #32 #55
Ketchup #6 #10
Hotdogs #4 #35
Mustard #7 #8
注意:头文件包含在.txt文件中,并且始终有五个项目需要重新进货
我的输出文件应为:
Inventory Data:
Buns #50 #63
Burgers #32 #55
Ketchup #6 #10
Hotdogs #4 #35
Mustard #7 #8
Restocking Data:
Buns #63 #13
Burgers #55 #23
Ketchup #10 #4
Hotdogs #35 #31
Mustard #8 #1
我的总输出应该是271,因为
Prices:
Buns $2
Burgers $5
Ketchup $1
Hotdogs $4
Mustard $2
阿姆罗很好心,帮我弄明白了如何拔出我需要的线,以及如何从我拥有的东西中减去我需要的。现在,我的最后一个难题(也是我需要克服的最后一个障碍,在我能够更好地个性化这个问题之前),是弄清楚如何编写一个输出原始数据以及重新进货数据的最终版本。它必须看起来像测试用例
function[restock_cost] = inventory2(file, prices)
%// Reads both files
fh = fopen(file, 'rt');
C = textscan(fh, '%s', 'Delimiter','');
inventory = C{1};
fclose(fh);
Original = C{:};
Original = char(Original);
fh2 = fopen(prices, 'rt');
D = textscan(fh2, '%s', 'Delimiter','');
prices = D{1};
fclose(fh2);
%// Breaks up inventory data
inventory(1) = [];
x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
x = vertcat(x{:});
itemName = x(:,1);
itemHave = str2double(x(:,2));
itemNeeded = str2double(x(:,3));
itemName = char(itemName);
%// Determines what needs to be restocked and how much is needed
Restock = itemNeeded - itemHave;
%// Breaks up price info
prices(1) = [];
x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
x = vertcat(x{:});
item = x(:,1);
prices = str2double(x(:,2));
%// Finds the price
restock_cost = sum((Restock .* prices));
%// gets the business name
[name, ~] = strtok(file,'_');
%// Finds the size of Original(may help)
[r,c] = size(Original);
[r2,c2] = size(itemName);
[r3,c3] = size(itemNeeded);
%// Starts to write my output file.
fh2 = fopen([name '_RestockingData.txt'], 'wt');
fprintf(fh2, 'Inventory Data: \n');
fprintf(fh2, '\n');
for i = 2:r %// Don't want the header included
fprintf(fh2, Original(i,1:c));
fprintf(fh2,'\n');
end
fprintf(fh2, '\n');
fprintf(fh2,'\n');
fprintf(fh2, 'Restocking Data: \n');
fprintf(fh2,'\n');
for j = 1:r2
fprintf(fh2, itemName(j,1:c2));
fprintf(fh2,' #%d ', itemNeeded(j));
fprintf(fh2, '#%d', Restock(j));
fprintf(fh2,'\n');
end
end
这很接近,但我需要它输出重新进货数据,在项目名称和编号之间只有一个空格。相反,它给了我:
Inventory Data:
Chips #40 #100
Lettuce #80 #90
Cheese #22 #60
Tortillas #65 #100
Tomatoes #40 #70
Restocking Data:
Chips #100 #60
Lettuce #90 #10
Cheese #60 #38
Tortillas #100 #35
Tomatoes #70 #30
我也试过:
Restock_Data = {};
Restock_Data = [Restock_Data, {itemName, itemNeeded, Restock}];
Restocking = {Restock_Data};
Kill_Cell = [{Restocking}];
for j = 1:r2
fprintf(fh2, Restock_Data(j));
fprintf(fh2,'\n');
end
我需要将我的单元格转换成其他形式,但是索引它(正如您在Kill_cell中看到的)不起作用。
结束
这就是一切。以下是给我的笔记,以防万一:
Notes:
- All inventory numbers will have a # in front of them
- All the prices will have a $ in front of them and will always be a
full dollar amount.
- When creating the new output every item should be seperated by a space
Ex. 'Chips #5 #2'
- There will always be 5 items to stock.
- If your output file is not EXACTLY the same as the solution txt file,
then you will receive 0 credit for it.
以下是使用textscan读取清单文件的一种方法:
fid = fopen('inventory.txt', 'rt');
C = textscan(fid, '%s #%d #%d', 'HeaderLines',1, 'CollectOutput',true);
fclose(fid);
已解析的数据:
>> C
C =
{5x1 cell} [5x2 int32]
>> C{1}
ans =
'Buns'
'Burgers'
'Ketchup'
'Hotdogs'
'Mustard'
>> C{2}
ans =
50 63
32 55
6 10
4 35
7 8
您也可以将该文件简单地作为字符串行的单元格数组来读取(我在以前回答您的问题时使用过这个): 在这种情况下,结果是:
>> C
C =
'Inventory Data:'
'Buns #50 #63'
'Burgers #32 #55'
'Ketchup #6 #10'
'Hotdogs #4 #35'
'Mustard #7 #8'
编辑: 正如我所展示的,首先我们将文件读取为字符串的单元格数组(文本行): 接下来,我们使用正则表达式匹配文本中的模式:
% parse inventory data
inventory(1) = [];
x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
x = vertcat(x{:});
itemName = x(:,1)
itemHave = str2double(x(:,2))
itemNeeded = str2double(x(:,3))
% parse prices data
prices(1) = [];
x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
x = vertcat(x{:});
item = x(:,1)
price = str2double(x(:,2))
最后,您可以将逻辑应用于重新进货库存,并打印所需输出…您熟悉
textscan
功能吗?这可能是最适合你需要的。还是应该使用较低级别的函数?我尝试使用textscan,但我不太明白如何正确使用它。我们不一定要学习文本扫描,但它在书中。只是解释得不太清楚。这正是我要写的代码。你帮我省去了麻烦。那么,组成单元阵列的%s是输入文件信息的位置,对吗?不是我,而是MATLAB。那么我猜“Delimiter”是默认的分隔符,所以我会说“/n”?然后我不太确定“比特”是干什么用的。填充空字符串还是什么?@JessicaMarie:textscan
用于读取数据行。第二个参数是“格式说明符”,它告诉textscan
要从每行读取多少个字段以及字段的类型。通过指定“%s”
,我是说我想读取一个字符串字段。最后一个选项(delimiter='
)在这里是必需的,因为默认情况下字段是以空格分隔的,并且通过指定空字符串('
)作为分隔符,字段将有效地继续到行的末尾。因此,我们每行得到一整行字符串。textscan
是一个功能强大的函数,可以接受许多选项。我建议你查阅文件以了解所有细节。。它的文档长达几页,这说明它有多么复杂:)@JessicaMarie:人们应该始终使用最好的工具来完成这项工作,对于这种文本处理,正则表达式非常灵活和强大。。。我很惊讶你没有被介绍给regex作为你大学课程的一部分,看到你张贴的大多数家庭作业问题都是这种性质的。
% read both files
fid = fopen('inventory.txt', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
inventory = C{1};
fclose(fid);
fid = fopen('prices.txt', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
prices = C{1};
fclose(fid);
% parse inventory data
inventory(1) = [];
x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
x = vertcat(x{:});
itemName = x(:,1)
itemHave = str2double(x(:,2))
itemNeeded = str2double(x(:,3))
% parse prices data
prices(1) = [];
x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
x = vertcat(x{:});
item = x(:,1)
price = str2double(x(:,2))